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 */ 36 char *flags_to_string(char *buffer, uint16_t flags) 37 { 38 strcpy(buffer, "default"); 39 if ((flags & POLARITY_ACTIVE_HIGH) == POLARITY_ACTIVE_HIGH) 40 strcpy(buffer, "high"); 41 else if ((flags & POLARITY_ACTIVE_LOW) == POLARITY_ACTIVE_LOW) 42 strcpy(buffer, "low"); 43 if ((flags & TRIGGER_EDGE) == TRIGGER_EDGE) 44 strncat(buffer, " edge", 5); 45 else if ((flags & TRIGGER_LEVEL) == TRIGGER_LEVEL) 46 strncat(buffer, " level", 6); 47 else 48 strncat(buffer, " default", 8); 49 50 return buffer; 51 } 52 53 void dbg_printf(const char *fmt, ...) 54 { 55 va_list args; 56 va_start(args, fmt); 57 vfprintf(stderr, fmt, args); 58 va_end(args); 59 } 60 61 void init_acpi(s_acpi * acpi) 62 { 63 memset(acpi, 0, sizeof(s_acpi)); 64 } 65 66 int parse_acpi(s_acpi * acpi) 67 { 68 int ret_val; 69 init_acpi(acpi); 70 71 /* Let's seach for RSDP table */ 72 if ((ret_val = search_rsdp(acpi)) != RSDP_TABLE_FOUND) 73 return ret_val; 74 75 /* Let's seach for RSDT table 76 * That's not a big deal not having it, XSDT is far more relevant */ 77 parse_rsdt(&acpi->rsdt); 78 if (parse_xsdt(acpi) != XSDT_TABLE_FOUND) { 79 DEBUG_PRINT(("XSDT Detection failed\n")); 80 for (int table=0; table <acpi->rsdt.entry_count; table++) { 81 parse_header((uint64_t *)acpi->rsdt.entry[table],acpi); 82 } 83 } 84 return ACPI_FOUND; 85 } 86 87 void get_acpi_description_header(uint8_t * q, s_acpi_description_header * adh) 88 { 89 cp_str_struct(adh->signature); 90 cp_struct(&adh->length); 91 cp_struct(&adh->revision); 92 cp_struct(&adh->checksum); 93 cp_str_struct(adh->oem_id); 94 cp_str_struct(adh->oem_table_id); 95 cp_struct(&adh->oem_revision); 96 cp_str_struct(adh->creator_id); 97 cp_struct(&adh->creator_revision); 98 DEBUG_PRINT(("acpi_header at %p = %s | %s | %s\n", q, adh->signature,adh->oem_id, adh->creator_id )); 99 } 100 101 bool parse_header(uint64_t *address, s_acpi *acpi) { 102 s_acpi_description_header adh; 103 memset(&adh, 0, sizeof(adh)); 104 105 get_acpi_description_header((uint8_t *)address, &adh); 106 107 /* Trying to determine the pointed table */ 108 /* Looking for FADT */ 109 if (memcmp(adh.signature, FACP, sizeof(FACP) - 1) == 0) { 110 DEBUG_PRINT(("FACP table found\n")); 111 s_fadt *f = &acpi->fadt; 112 s_facs *fa = &acpi->facs; 113 s_dsdt *d = &acpi->dsdt; 114 /* This structure is valid, let's fill it */ 115 f->valid = true; 116 f->address = address; 117 memcpy(&f->header, &adh, sizeof(adh)); 118 parse_fadt(f); 119 120 /* FACS wasn't already detected 121 * FADT points to it, let's try to detect it */ 122 if (fa->valid == false) { 123 fa->address = (uint64_t *)f->x_firmware_ctrl; 124 parse_facs(fa); 125 if (fa->valid == false) { 126 /* Let's try again */ 127 fa->address = (uint64_t *)f->firmware_ctrl; 128 parse_facs(fa); 129 } 130 } 131 132 /* DSDT wasn't already detected 133 * FADT points to it, let's try to detect it */ 134 if (d->valid == false) { 135 s_acpi_description_header new_adh; 136 get_acpi_description_header((uint8_t *)f->x_dsdt, 137 &new_adh); 138 if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 0) { 139 DEBUG_PRINT(("DSDT table found via x_dsdt\n")); 140 d->valid = true; 141 d->address = (uint64_t *)f->x_dsdt; 142 memcpy(&d->header, &new_adh, sizeof(new_adh)); 143 parse_dsdt(d); 144 } else { 145 /* Let's try again */ 146 get_acpi_description_header((uint8_t *)f->dsdt_address, 147 &new_adh); 148 if (memcmp(new_adh.signature, DSDT, sizeof(DSDT) - 1) == 149 0) { 150 DEBUG_PRINT(("DSDT table found via dsdt_address\n")); 151 d->valid = true; 152 d->address = (uint64_t *)f->dsdt_address; 153 memcpy(&d->header, &new_adh, sizeof(new_adh)); 154 parse_dsdt(d); 155 } 156 } 157 } 158 } /* Looking for MADT */ 159 else if (memcmp(adh.signature, APIC, sizeof(APIC) - 1) == 0) { 160 DEBUG_PRINT(("MADT table found\n")); 161 s_madt *m = &acpi->madt; 162 /* This structure is valid, let's fill it */ 163 m->valid = true; 164 m->address =address; 165 memcpy(&m->header, &adh, sizeof(adh)); 166 parse_madt(acpi); 167 } else if (memcmp(adh.signature, DSDT, sizeof(DSDT) - 1) == 0) { 168 DEBUG_PRINT(("DSDT table found\n")); 169 s_dsdt *d = &acpi->dsdt; 170 /* This structure is valid, let's fill it */ 171 d->valid = true; 172 d->address = address; 173 memcpy(&d->header, &adh, sizeof(adh)); 174 parse_dsdt(d); 175 /* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */ 176 } else if ((memcmp(adh.signature, SSDT, sizeof(SSDT) - 1) == 0) 177 || (memcmp(adh.signature, PSDT, sizeof(PSDT) - 1) == 0)) { 178 179 DEBUG_PRINT(("SSDT table found with %s \n",adh.signature)); 180 181 if ((acpi->ssdt_count >= MAX_SSDT - 1)) 182 return false; 183 184 /* We can have many SSDT, so let's allocate a new one */ 185 if ((acpi->ssdt[acpi->ssdt_count] = 186 malloc(sizeof(s_ssdt))) == NULL) 187 return false; 188 s_ssdt *s = acpi->ssdt[acpi->ssdt_count]; 189 190 /* This structure is valid, let's fill it */ 191 s->valid = true; 192 s->address = address; 193 memcpy(&s->header, &adh, sizeof(adh)); 194 195 /* Searching how much definition blocks we must copy */ 196 uint32_t definition_block_size = adh.length - ACPI_HEADER_SIZE; 197 if ((s->definition_block = 198 malloc(definition_block_size)) != NULL) { 199 memcpy(s->definition_block, 200 (s->address + ACPI_HEADER_SIZE), 201 definition_block_size); 202 } 203 /* Increment the number of ssdt we have */ 204 acpi->ssdt_count++; 205 } else if (memcmp(adh.signature, SBST, sizeof(SBST) - 1) == 0) { 206 DEBUG_PRINT(("SBST table found\n")); 207 s_sbst *s = &acpi->sbst; 208 /* This structure is valid, let's fill it */ 209 s->valid = true; 210 s->address = address; 211 memcpy(&s->header, &adh, sizeof(adh)); 212 parse_sbst(s); 213 } else if (memcmp(adh.signature, ECDT, sizeof(ECDT) - 1) == 0) { 214 DEBUG_PRINT(("ECDT table found\n")); 215 s_ecdt *e = &acpi->ecdt; 216 /* This structure is valid, let's fill it */ 217 e->valid = true; 218 e->address = address; 219 memcpy(&e->header, &adh, sizeof(adh)); 220 parse_ecdt(e); 221 } else if (memcmp(adh.signature, HPET, sizeof(HPET) - 1) == 0) { 222 DEBUG_PRINT(("HPET table found\n")); 223 s_hpet *h = &acpi->hpet; 224 /* This structure is valid, let's fill it */ 225 h->valid = true; 226 h->address = address; 227 memcpy(&h->header, &adh, sizeof(adh)); 228 } else if (memcmp(adh.signature, TCPA, sizeof(TCPA) - 1) == 0) { 229 DEBUG_PRINT(("TCPA table found\n")); 230 s_tcpa *t = &acpi->tcpa; 231 /* This structure is valid, let's fill it */ 232 t->valid = true; 233 t->address = address; 234 memcpy(&t->header, &adh, sizeof(adh)); 235 } else if (memcmp(adh.signature, MCFG, sizeof(MCFG) - 1) == 0) { 236 DEBUG_PRINT(("MCFG table found\n")); 237 s_mcfg *m = &acpi->mcfg; 238 /* This structure is valid, let's fill it */ 239 m->valid = true; 240 m->address = address; 241 memcpy(&m->header, &adh, sizeof(adh)); 242 } else if (memcmp(adh.signature, SLIC, sizeof(SLIC) - 1) == 0) { 243 DEBUG_PRINT(("SLIC table found\n")); 244 s_slic *s = &acpi->slic; 245 /* This structure is valid, let's fill it */ 246 s->valid = true; 247 s->address = address; 248 memcpy(&s->header, &adh, sizeof(adh)); 249 } else if (memcmp(adh.signature, BOOT, sizeof(BOOT) - 1) == 0) { 250 DEBUG_PRINT(("BOOT table found\n")); 251 s_boot *b = &acpi->boot; 252 /* This structure is valid, let's fill it */ 253 b->valid = true; 254 b->address = address; 255 memcpy(&b->header, &adh, sizeof(adh)); 256 } 257 258 return true; 259 } 260