1 /* 2 * acpi_tables.c - ACPI Boot-Time Table Parsing 3 * 4 * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 5 * 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 * 24 */ 25 26 #include <linux/config.h> 27 #include <linux/init.h> 28 #include <linux/kernel.h> 29 #include <linux/sched.h> 30 #include <linux/smp.h> 31 #include <linux/string.h> 32 #include <linux/types.h> 33 #include <linux/irq.h> 34 #include <linux/errno.h> 35 #include <linux/acpi.h> 36 #include <linux/bootmem.h> 37 38 #define PREFIX "ACPI: " 39 40 #define ACPI_MAX_TABLES 128 41 42 static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { 43 [ACPI_TABLE_UNKNOWN] = "????", 44 [ACPI_APIC] = "APIC", 45 [ACPI_BOOT] = "BOOT", 46 [ACPI_DBGP] = "DBGP", 47 [ACPI_DSDT] = "DSDT", 48 [ACPI_ECDT] = "ECDT", 49 [ACPI_ETDT] = "ETDT", 50 [ACPI_FADT] = "FACP", 51 [ACPI_FACS] = "FACS", 52 [ACPI_OEMX] = "OEM", 53 [ACPI_PSDT] = "PSDT", 54 [ACPI_SBST] = "SBST", 55 [ACPI_SLIT] = "SLIT", 56 [ACPI_SPCR] = "SPCR", 57 [ACPI_SRAT] = "SRAT", 58 [ACPI_SSDT] = "SSDT", 59 [ACPI_SPMI] = "SPMI", 60 [ACPI_HPET] = "HPET", 61 [ACPI_MCFG] = "MCFG", 62 }; 63 64 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; 65 static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; 66 67 /* System Description Table (RSDT/XSDT) */ 68 struct acpi_table_sdt { 69 unsigned long pa; 70 enum acpi_table_id id; 71 unsigned long size; 72 } __attribute__ ((packed)); 73 74 static unsigned long sdt_pa; /* Physical Address */ 75 static unsigned long sdt_count; /* Table count */ 76 77 static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata; 78 79 void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr) 80 { 81 char *name = NULL; 82 83 if (!header) 84 return; 85 86 /* Some table signatures aren't good table names */ 87 88 if (!strncmp((char *)&header->signature, 89 acpi_table_signatures[ACPI_APIC], 90 sizeof(header->signature))) { 91 name = "MADT"; 92 } else if (!strncmp((char *)&header->signature, 93 acpi_table_signatures[ACPI_FADT], 94 sizeof(header->signature))) { 95 name = "FADT"; 96 } else 97 name = header->signature; 98 99 printk(KERN_DEBUG PREFIX 100 "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name, 101 header->revision, header->oem_id, header->oem_table_id, 102 header->oem_revision, header->asl_compiler_id, 103 header->asl_compiler_revision, (void *)phys_addr); 104 } 105 106 void acpi_table_print_madt_entry(acpi_table_entry_header * header) 107 { 108 if (!header) 109 return; 110 111 switch (header->type) { 112 113 case ACPI_MADT_LAPIC: 114 { 115 struct acpi_table_lapic *p = 116 (struct acpi_table_lapic *)header; 117 printk(KERN_INFO PREFIX 118 "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", 119 p->acpi_id, p->id, 120 p->flags.enabled ? "enabled" : "disabled"); 121 } 122 break; 123 124 case ACPI_MADT_IOAPIC: 125 { 126 struct acpi_table_ioapic *p = 127 (struct acpi_table_ioapic *)header; 128 printk(KERN_INFO PREFIX 129 "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", 130 p->id, p->address, p->global_irq_base); 131 } 132 break; 133 134 case ACPI_MADT_INT_SRC_OVR: 135 { 136 struct acpi_table_int_src_ovr *p = 137 (struct acpi_table_int_src_ovr *)header; 138 printk(KERN_INFO PREFIX 139 "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", 140 p->bus, p->bus_irq, p->global_irq, 141 mps_inti_flags_polarity[p->flags.polarity], 142 mps_inti_flags_trigger[p->flags.trigger]); 143 if (p->flags.reserved) 144 printk(KERN_INFO PREFIX 145 "INT_SRC_OVR unexpected reserved flags: 0x%x\n", 146 p->flags.reserved); 147 148 } 149 break; 150 151 case ACPI_MADT_NMI_SRC: 152 { 153 struct acpi_table_nmi_src *p = 154 (struct acpi_table_nmi_src *)header; 155 printk(KERN_INFO PREFIX 156 "NMI_SRC (%s %s global_irq %d)\n", 157 mps_inti_flags_polarity[p->flags.polarity], 158 mps_inti_flags_trigger[p->flags.trigger], 159 p->global_irq); 160 } 161 break; 162 163 case ACPI_MADT_LAPIC_NMI: 164 { 165 struct acpi_table_lapic_nmi *p = 166 (struct acpi_table_lapic_nmi *)header; 167 printk(KERN_INFO PREFIX 168 "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", 169 p->acpi_id, 170 mps_inti_flags_polarity[p->flags.polarity], 171 mps_inti_flags_trigger[p->flags.trigger], 172 p->lint); 173 } 174 break; 175 176 case ACPI_MADT_LAPIC_ADDR_OVR: 177 { 178 struct acpi_table_lapic_addr_ovr *p = 179 (struct acpi_table_lapic_addr_ovr *)header; 180 printk(KERN_INFO PREFIX 181 "LAPIC_ADDR_OVR (address[%p])\n", 182 (void *)(unsigned long)p->address); 183 } 184 break; 185 186 case ACPI_MADT_IOSAPIC: 187 { 188 struct acpi_table_iosapic *p = 189 (struct acpi_table_iosapic *)header; 190 printk(KERN_INFO PREFIX 191 "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", 192 p->id, (void *)(unsigned long)p->address, 193 p->global_irq_base); 194 } 195 break; 196 197 case ACPI_MADT_LSAPIC: 198 { 199 struct acpi_table_lsapic *p = 200 (struct acpi_table_lsapic *)header; 201 printk(KERN_INFO PREFIX 202 "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", 203 p->acpi_id, p->id, p->eid, 204 p->flags.enabled ? "enabled" : "disabled"); 205 } 206 break; 207 208 case ACPI_MADT_PLAT_INT_SRC: 209 { 210 struct acpi_table_plat_int_src *p = 211 (struct acpi_table_plat_int_src *)header; 212 printk(KERN_INFO PREFIX 213 "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", 214 mps_inti_flags_polarity[p->flags.polarity], 215 mps_inti_flags_trigger[p->flags.trigger], 216 p->type, p->id, p->eid, p->iosapic_vector, 217 p->global_irq); 218 } 219 break; 220 221 default: 222 printk(KERN_WARNING PREFIX 223 "Found unsupported MADT entry (type = 0x%x)\n", 224 header->type); 225 break; 226 } 227 } 228 229 static int 230 acpi_table_compute_checksum(void *table_pointer, unsigned long length) 231 { 232 u8 *p = (u8 *) table_pointer; 233 unsigned long remains = length; 234 unsigned long sum = 0; 235 236 if (!p || !length) 237 return -EINVAL; 238 239 while (remains--) 240 sum += *p++; 241 242 return (sum & 0xFF); 243 } 244 245 /* 246 * acpi_get_table_header_early() 247 * for acpi_blacklisted(), acpi_table_get_sdt() 248 */ 249 int __init 250 acpi_get_table_header_early(enum acpi_table_id id, 251 struct acpi_table_header **header) 252 { 253 unsigned int i; 254 enum acpi_table_id temp_id; 255 256 /* DSDT is different from the rest */ 257 if (id == ACPI_DSDT) 258 temp_id = ACPI_FADT; 259 else 260 temp_id = id; 261 262 /* Locate the table. */ 263 264 for (i = 0; i < sdt_count; i++) { 265 if (sdt_entry[i].id != temp_id) 266 continue; 267 *header = (void *) 268 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); 269 if (!*header) { 270 printk(KERN_WARNING PREFIX "Unable to map %s\n", 271 acpi_table_signatures[temp_id]); 272 return -ENODEV; 273 } 274 break; 275 } 276 277 if (!*header) { 278 printk(KERN_WARNING PREFIX "%s not present\n", 279 acpi_table_signatures[id]); 280 return -ENODEV; 281 } 282 283 /* Map the DSDT header via the pointer in the FADT */ 284 if (id == ACPI_DSDT) { 285 struct fadt_descriptor_rev2 *fadt = 286 (struct fadt_descriptor_rev2 *)*header; 287 288 if (fadt->revision == 3 && fadt->Xdsdt) { 289 *header = (void *)__acpi_map_table(fadt->Xdsdt, 290 sizeof(struct 291 acpi_table_header)); 292 } else if (fadt->V1_dsdt) { 293 *header = (void *)__acpi_map_table(fadt->V1_dsdt, 294 sizeof(struct 295 acpi_table_header)); 296 } else 297 *header = NULL; 298 299 if (!*header) { 300 printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); 301 return -ENODEV; 302 } 303 } 304 305 return 0; 306 } 307 308 int __init 309 acpi_table_parse_madt_family(enum acpi_table_id id, 310 unsigned long madt_size, 311 int entry_id, 312 acpi_madt_entry_handler handler, 313 unsigned int max_entries) 314 { 315 void *madt = NULL; 316 acpi_table_entry_header *entry; 317 unsigned int count = 0; 318 unsigned long madt_end; 319 unsigned int i; 320 321 if (!handler) 322 return -EINVAL; 323 324 /* Locate the MADT (if exists). There should only be one. */ 325 326 for (i = 0; i < sdt_count; i++) { 327 if (sdt_entry[i].id != id) 328 continue; 329 madt = (void *) 330 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); 331 if (!madt) { 332 printk(KERN_WARNING PREFIX "Unable to map %s\n", 333 acpi_table_signatures[id]); 334 return -ENODEV; 335 } 336 break; 337 } 338 339 if (!madt) { 340 printk(KERN_WARNING PREFIX "%s not present\n", 341 acpi_table_signatures[id]); 342 return -ENODEV; 343 } 344 345 madt_end = (unsigned long)madt + sdt_entry[i].size; 346 347 /* Parse all entries looking for a match. */ 348 349 entry = (acpi_table_entry_header *) 350 ((unsigned long)madt + madt_size); 351 352 while (((unsigned long)entry) + sizeof(acpi_table_entry_header) < 353 madt_end) { 354 if (entry->type == entry_id 355 && (!max_entries || count++ < max_entries)) 356 if (handler(entry, madt_end)) 357 return -EINVAL; 358 359 entry = (acpi_table_entry_header *) 360 ((unsigned long)entry + entry->length); 361 } 362 if (max_entries && count > max_entries) { 363 printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of " 364 "%i found\n", acpi_table_signatures[id], entry_id, 365 count - max_entries, count); 366 } 367 368 return count; 369 } 370 371 int __init 372 acpi_table_parse_madt(enum acpi_madt_entry_id id, 373 acpi_madt_entry_handler handler, unsigned int max_entries) 374 { 375 return acpi_table_parse_madt_family(ACPI_APIC, 376 sizeof(struct acpi_table_madt), id, 377 handler, max_entries); 378 } 379 380 int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler) 381 { 382 int count = 0; 383 unsigned int i = 0; 384 385 if (!handler) 386 return -EINVAL; 387 388 for (i = 0; i < sdt_count; i++) { 389 if (sdt_entry[i].id != id) 390 continue; 391 count++; 392 if (count == 1) 393 handler(sdt_entry[i].pa, sdt_entry[i].size); 394 395 else 396 printk(KERN_WARNING PREFIX 397 "%d duplicate %s table ignored.\n", count, 398 acpi_table_signatures[id]); 399 } 400 401 return count; 402 } 403 404 static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp) 405 { 406 struct acpi_table_header *header = NULL; 407 unsigned int i, id = 0; 408 409 if (!rsdp) 410 return -EINVAL; 411 412 /* First check XSDT (but only on ACPI 2.0-compatible systems) */ 413 414 if ((rsdp->revision >= 2) && 415 (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) { 416 417 struct acpi_table_xsdt *mapped_xsdt = NULL; 418 419 sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address; 420 421 /* map in just the header */ 422 header = (struct acpi_table_header *) 423 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); 424 425 if (!header) { 426 printk(KERN_WARNING PREFIX 427 "Unable to map XSDT header\n"); 428 return -ENODEV; 429 } 430 431 /* remap in the entire table before processing */ 432 mapped_xsdt = (struct acpi_table_xsdt *) 433 __acpi_map_table(sdt_pa, header->length); 434 if (!mapped_xsdt) { 435 printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); 436 return -ENODEV; 437 } 438 header = &mapped_xsdt->header; 439 440 if (strncmp(header->signature, "XSDT", 4)) { 441 printk(KERN_WARNING PREFIX 442 "XSDT signature incorrect\n"); 443 return -ENODEV; 444 } 445 446 if (acpi_table_compute_checksum(header, header->length)) { 447 printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n"); 448 return -ENODEV; 449 } 450 451 sdt_count = 452 (header->length - sizeof(struct acpi_table_header)) >> 3; 453 if (sdt_count > ACPI_MAX_TABLES) { 454 printk(KERN_WARNING PREFIX 455 "Truncated %lu XSDT entries\n", 456 (sdt_count - ACPI_MAX_TABLES)); 457 sdt_count = ACPI_MAX_TABLES; 458 } 459 460 for (i = 0; i < sdt_count; i++) 461 sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i]; 462 } 463 464 /* Then check RSDT */ 465 466 else if (rsdp->rsdt_address) { 467 468 struct acpi_table_rsdt *mapped_rsdt = NULL; 469 470 sdt_pa = rsdp->rsdt_address; 471 472 /* map in just the header */ 473 header = (struct acpi_table_header *) 474 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); 475 if (!header) { 476 printk(KERN_WARNING PREFIX 477 "Unable to map RSDT header\n"); 478 return -ENODEV; 479 } 480 481 /* remap in the entire table before processing */ 482 mapped_rsdt = (struct acpi_table_rsdt *) 483 __acpi_map_table(sdt_pa, header->length); 484 if (!mapped_rsdt) { 485 printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); 486 return -ENODEV; 487 } 488 header = &mapped_rsdt->header; 489 490 if (strncmp(header->signature, "RSDT", 4)) { 491 printk(KERN_WARNING PREFIX 492 "RSDT signature incorrect\n"); 493 return -ENODEV; 494 } 495 496 if (acpi_table_compute_checksum(header, header->length)) { 497 printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n"); 498 return -ENODEV; 499 } 500 501 sdt_count = 502 (header->length - sizeof(struct acpi_table_header)) >> 2; 503 if (sdt_count > ACPI_MAX_TABLES) { 504 printk(KERN_WARNING PREFIX 505 "Truncated %lu RSDT entries\n", 506 (sdt_count - ACPI_MAX_TABLES)); 507 sdt_count = ACPI_MAX_TABLES; 508 } 509 510 for (i = 0; i < sdt_count; i++) 511 sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i]; 512 } 513 514 else { 515 printk(KERN_WARNING PREFIX 516 "No System Description Table (RSDT/XSDT) specified in RSDP\n"); 517 return -ENODEV; 518 } 519 520 acpi_table_print(header, sdt_pa); 521 522 for (i = 0; i < sdt_count; i++) { 523 524 /* map in just the header */ 525 header = (struct acpi_table_header *) 526 __acpi_map_table(sdt_entry[i].pa, 527 sizeof(struct acpi_table_header)); 528 if (!header) 529 continue; 530 531 /* remap in the entire table before processing */ 532 header = (struct acpi_table_header *) 533 __acpi_map_table(sdt_entry[i].pa, header->length); 534 if (!header) 535 continue; 536 537 acpi_table_print(header, sdt_entry[i].pa); 538 539 if (acpi_table_compute_checksum(header, header->length)) { 540 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); 541 continue; 542 } 543 544 sdt_entry[i].size = header->length; 545 546 for (id = 0; id < ACPI_TABLE_COUNT; id++) { 547 if (!strncmp((char *)&header->signature, 548 acpi_table_signatures[id], 549 sizeof(header->signature))) { 550 sdt_entry[i].id = id; 551 } 552 } 553 } 554 555 /* 556 * The DSDT is *not* in the RSDT (why not? no idea.) but we want 557 * to print its info, because this is what people usually blacklist 558 * against. Unfortunately, we don't know the phys_addr, so just 559 * print 0. Maybe no one will notice. 560 */ 561 if (!acpi_get_table_header_early(ACPI_DSDT, &header)) 562 acpi_table_print(header, 0); 563 564 return 0; 565 } 566 567 /* 568 * acpi_table_init() 569 * 570 * find RSDP, find and checksum SDT/XSDT. 571 * checksum all tables, print SDT/XSDT 572 * 573 * result: sdt_entry[] is initialized 574 */ 575 576 int __init acpi_table_init(void) 577 { 578 struct acpi_table_rsdp *rsdp = NULL; 579 unsigned long rsdp_phys = 0; 580 int result = 0; 581 582 /* Locate and map the Root System Description Table (RSDP) */ 583 584 rsdp_phys = acpi_find_rsdp(); 585 if (!rsdp_phys) { 586 printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); 587 return -ENODEV; 588 } 589 590 rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys); 591 if (!rsdp) { 592 printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); 593 return -ENODEV; 594 } 595 596 printk(KERN_DEBUG PREFIX 597 "RSDP (v%3.3d %6.6s ) @ 0x%p\n", 598 rsdp->revision, rsdp->oem_id, (void *)rsdp_phys); 599 600 if (rsdp->revision < 2) 601 result = 602 acpi_table_compute_checksum(rsdp, 603 sizeof(struct acpi_table_rsdp)); 604 else 605 result = 606 acpi_table_compute_checksum(rsdp, 607 ((struct acpi20_table_rsdp *) 608 rsdp)->length); 609 610 if (result) { 611 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); 612 return -ENODEV; 613 } 614 615 /* Locate and map the System Description table (RSDT/XSDT) */ 616 617 if (acpi_table_get_sdt(rsdp)) 618 return -ENODEV; 619 620 return 0; 621 } 622