syslinux/com32/gpllib/acpi/acpi.c
<<
>>
Prefs
   1/* ----------------------------------------------------------------------- *
   2 *
   3 *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
   4 *
   5 *   Permission is hereby granted, free of charge, to any person
   6 *   obtaining a copy of this software and associated documentation
   7 *   files (the "Software"), to deal in the Software without
   8 *   restriction, including without limitation the rights to use,
   9 *   copy, modify, merge, publish, distribute, sublicense, and/or
  10 *   sell copies of the Software, and to permit persons to whom
  11 *   the Software is furnished to do so, subject to the following
  12 *   conditions:
  13 *
  14 *   The above copyright notice and this permission notice shall
  15 *   be included in all copies or substantial portions of the Software.
  16 *
  17 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24 *   OTHER DEALINGS IN THE SOFTWARE.
  25 *
  26 * -----------------------------------------------------------------------
  27*/
  28
  29#include <stdio.h>
  30#include <stdlib.h>
  31#include <string.h>
  32#include <memory.h>
  33#include "acpi/acpi.h"
  34
  35/* M1PS flags have to be interpreted as strings */
  36char *flags_to_string(char *buffer, uint16_t flags)
  37{
  38    memset(buffer, 0, sizeof(buffer));
  39    strcpy(buffer, "default");
  40    if ((flags & POLARITY_ACTIVE_HIGH) == POLARITY_ACTIVE_HIGH)
  41        strcpy(buffer, "high");
  42    else if ((flags & POLARITY_ACTIVE_LOW) == POLARITY_ACTIVE_LOW)
  43        strcpy(buffer, "low");
  44    if ((flags & TRIGGER_EDGE) == TRIGGER_EDGE)
  45        strncat(buffer, " edge", 5);
  46    else if ((flags & TRIGGER_LEVEL) == TRIGGER_LEVEL)
  47        strncat(buffer, " level", 6);
  48    else
  49        strncat(buffer, " default", 8);
  50
  51    return buffer;
  52}
  53
  54void dbg_printf(const char *fmt, ...)
  55{
  56        va_list args;
  57        va_start(args, fmt);
  58        vfprintf(stderr, fmt, args);
  59        va_end(args);
  60}
  61
  62void init_acpi(s_acpi * acpi)
  63{
  64    memset(acpi, 0, sizeof(s_acpi));
  65}
  66
  67int parse_acpi(s_acpi * acpi)
  68{
  69    int ret_val;
  70    init_acpi(acpi);
  71
  72    /* Let's seach for RSDP table */
  73    if ((ret_val = search_rsdp(acpi)) != RSDP_TABLE_FOUND)
  74        return ret_val;
  75
  76    /* Let's seach for RSDT table
  77     * That's not a big deal not having it, XSDT is far more relevant */
  78    parse_rsdt(&acpi->rsdt);
  79    if (parse_xsdt(acpi) != XSDT_TABLE_FOUND) {
  80            DEBUG_PRINT(("XSDT Detection failed\n"));
  81            for (int table=0; table <acpi->rsdt.entry_count; table++) {
  82                parse_header((uint64_t *)acpi->rsdt.entry[table],acpi);
  83            }
  84    }
  85    return ACPI_FOUND;
  86}
  87
  88void get_acpi_description_header(uint8_t * q, s_acpi_description_header * adh)
  89{
  90    cp_str_struct(adh->signature);
  91    cp_struct(&adh->length);
  92    cp_struct(&adh->revision);
  93    cp_struct(&adh->checksum);
  94    cp_str_struct(adh->oem_id);
  95    cp_str_struct(adh->oem_table_id);
  96    cp_struct(&adh->oem_revision);
  97    cp_str_struct(adh->creator_id);
  98    cp_struct(&adh->creator_revision);
  99    DEBUG_PRINT(("acpi_header at %p = %s | %s | %s\n", q, adh->signature,adh->oem_id, adh->creator_id ));
 100}
 101
 102bool parse_header(uint64_t *address, s_acpi *acpi) {
 103            s_acpi_description_header adh;
 104            memset(&adh, 0, sizeof(adh));
 105
 106            get_acpi_description_header((uint8_t *)address, &adh);
 107
 108            /* Trying to determine the pointed table */
 109            /* Looking for FADT */
 110            if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) {
 111                DEBUG_PRINT(("FACP table found\n"));
 112                s_fadt *f = &acpi->fadt;
 113                s_facs *fa = &acpi->facs;
 114                s_dsdt *d = &acpi->dsdt;
 115                /* This structure is valid, let's fill it */
 116                f->valid = true;
 117                f->address = address;
 118                memcpy(&f->header, &adh, sizeof(adh));
 119                parse_fadt(f);
 120
 121                /* FACS wasn't already detected
 122                 * FADT points to it, let's try to detect it */
 123                if (fa->valid == false) {
 124                    fa->address = (uint64_t *)f->x_firmware_ctrl;
 125                    parse_facs(fa);
 126                    if (fa->valid == false) {
 127                        /* Let's try again */
 128                        fa->address = (uint64_t *)f->firmware_ctrl;
 129                        parse_facs(fa);
 130                    }
 131                }
 132
 133                /* DSDT wasn't already detected
 134                 * FADT points to it, let's try to detect it */
 135                if (d->valid == false) {
 136                    s_acpi_description_header new_adh;
 137                    get_acpi_description_header((uint8_t *)f->x_dsdt,
 138                                                &new_adh);
 139                    if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
 140                        DEBUG_PRINT(("DSDT table found via x_dsdt\n"));
 141                        d->valid = true;
 142                        d->address = (uint64_t *)f->x_dsdt;
 143                        memcpy(&d->header, &new_adh, sizeof(new_adh));
 144                        parse_dsdt(d);
 145                    } else {
 146                        /* Let's try again */
 147                        get_acpi_description_header((uint8_t *)f->dsdt_address,
 148                                                    &new_adh);
 149                        if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) ==
 150                            0) {
 151                            DEBUG_PRINT(("DSDT table found via dsdt_address\n"));
 152                            d->valid = true;
 153                            d->address = (uint64_t *)f->dsdt_address;
 154                            memcpy(&d->header, &new_adh, sizeof(new_adh));
 155                            parse_dsdt(d);
 156                        }
 157                    }
 158                }
 159            } /* Looking for MADT */
 160            else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) {
 161                DEBUG_PRINT(("MADT table found\n"));
 162                s_madt *m = &acpi->madt;
 163                /* This structure is valid, let's fill it */
 164                m->valid = true;
 165                m->address =address;
 166                memcpy(&m->header, &adh, sizeof(adh));
 167                parse_madt(acpi);
 168            } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) {
 169                DEBUG_PRINT(("DSDT table found\n"));
 170                s_dsdt *d = &acpi->dsdt;
 171                /* This structure is valid, let's fill it */
 172                d->valid = true;
 173                d->address = address;
 174                memcpy(&d->header, &adh, sizeof(adh));
 175                parse_dsdt(d);
 176                /* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */
 177            } else if ((memcmp(adh.signature, SSDT, sizeof(SSDT) - 1) == 0)
 178                       || (memcmp(adh.signature, PSDT, sizeof(PSDT) - 1) == 0)) {
 179                
 180                DEBUG_PRINT(("SSDT table found with %s \n",adh.signature));
 181
 182                if ((acpi->ssdt_count >= MAX_SSDT - 1))
 183                    return false;
 184
 185                /* We can have many SSDT, so let's allocate a new one */
 186                if ((acpi->ssdt[acpi->ssdt_count] =
 187                     malloc(sizeof(s_ssdt))) == NULL)
 188                    return false;
 189                s_ssdt *s = acpi->ssdt[acpi->ssdt_count];
 190
 191                /* This structure is valid, let's fill it */
 192                s->valid = true;
 193                s->address = address;
 194                memcpy(&s->header, &adh, sizeof(adh));
 195
 196                /* Searching how much definition blocks we must copy */
 197                uint32_t definition_block_size = adh.length - ACPI_HEADER_SIZE;
 198                if ((s->definition_block =
 199                     malloc(definition_block_size)) != NULL) {
 200                    memcpy(s->definition_block,
 201                           (s->address + ACPI_HEADER_SIZE),
 202                           definition_block_size);
 203                }
 204                /* Increment the number of ssdt we have */
 205                acpi->ssdt_count++;
 206            } else if (memcmp(adh.signature, SBST, sizeof(SBST) - 1) == 0) {
 207                DEBUG_PRINT(("SBST table found\n"));
 208                s_sbst *s = &acpi->sbst;
 209                /* This structure is valid, let's fill it */
 210                s->valid = true;
 211                s->address = address;
 212                memcpy(&s->header, &adh, sizeof(adh));
 213                parse_sbst(s);
 214            } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) {
 215                DEBUG_PRINT(("ECDT table found\n"));
 216                s_ecdt *e = &acpi->ecdt;
 217                /* This structure is valid, let's fill it */
 218                e->valid = true;
 219                e->address = address;
 220                memcpy(&e->header, &adh, sizeof(adh));
 221                parse_ecdt(e);
 222            }  else if (memcmp(adh.signature, HPET, sizeof(HPET) - 1) == 0) {
 223                DEBUG_PRINT(("HPET table found\n"));
 224                s_hpet *h = &acpi->hpet;
 225                /* This structure is valid, let's fill it */
 226                h->valid = true;
 227                h->address = address;
 228                memcpy(&h->header, &adh, sizeof(adh));
 229            } else if (memcmp(adh.signature, TCPA, sizeof(TCPA) - 1) == 0) {
 230                DEBUG_PRINT(("TCPA table found\n"));
 231                s_tcpa *t = &acpi->tcpa;
 232                /* This structure is valid, let's fill it */
 233                t->valid = true;
 234                t->address = address;
 235                memcpy(&t->header, &adh, sizeof(adh));
 236            } else if (memcmp(adh.signature, MCFG, sizeof(MCFG) - 1) == 0) {
 237                DEBUG_PRINT(("MCFG table found\n"));
 238                s_mcfg *m = &acpi->mcfg;
 239                /* This structure is valid, let's fill it */
 240                m->valid = true;
 241                m->address = address;
 242                memcpy(&m->header, &adh, sizeof(adh));
 243            } else if (memcmp(adh.signature, SLIC, sizeof(SLIC) - 1) == 0) {
 244                DEBUG_PRINT(("SLIC table found\n"));
 245                s_slic *s = &acpi->slic;
 246                /* This structure is valid, let's fill it */
 247                s->valid = true;
 248                s->address = address;
 249                memcpy(&s->header, &adh, sizeof(adh));
 250            } else if (memcmp(adh.signature, BOOT, sizeof(BOOT) - 1) == 0) {
 251                DEBUG_PRINT(("BOOT table found\n"));
 252                s_boot *b = &acpi->boot;
 253                /* This structure is valid, let's fill it */
 254                b->valid = true;
 255                b->address = address;
 256                memcpy(&b->header, &adh, sizeof(adh));
 257            }
 258            
 259            return true;
 260}
 261
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.