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 256 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]; 78 79 void 80 acpi_table_print ( 81 struct acpi_table_header *header, 82 unsigned long phys_addr) 83 { 84 char *name = NULL; 85 86 if (!header) 87 return; 88 89 /* Some table signatures aren't good table names */ 90 91 if (!strncmp((char *) &header->signature, 92 acpi_table_signatures[ACPI_APIC], 93 sizeof(header->signature))) { 94 name = "MADT"; 95 } 96 else if (!strncmp((char *) &header->signature, 97 acpi_table_signatures[ACPI_FADT], 98 sizeof(header->signature))) { 99 name = "FADT"; 100 } 101 else 102 name = header->signature; 103 104 printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", 105 name, header->revision, header->oem_id, 106 header->oem_table_id, header->oem_revision, 107 header->asl_compiler_id, header->asl_compiler_revision, 108 (void *) phys_addr); 109 } 110 111 112 void 113 acpi_table_print_madt_entry ( 114 acpi_table_entry_header *header) 115 { 116 if (!header) 117 return; 118 119 switch (header->type) { 120 121 case ACPI_MADT_LAPIC: 122 { 123 struct acpi_table_lapic *p = 124 (struct acpi_table_lapic*) header; 125 printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", 126 p->acpi_id, p->id, p->flags.enabled?"enabled":"disabled"); 127 } 128 break; 129 130 case ACPI_MADT_IOAPIC: 131 { 132 struct acpi_table_ioapic *p = 133 (struct acpi_table_ioapic*) header; 134 printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", 135 p->id, p->address, p->global_irq_base); 136 } 137 break; 138 139 case ACPI_MADT_INT_SRC_OVR: 140 { 141 struct acpi_table_int_src_ovr *p = 142 (struct acpi_table_int_src_ovr*) header; 143 printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", 144 p->bus, p->bus_irq, p->global_irq, 145 mps_inti_flags_polarity[p->flags.polarity], 146 mps_inti_flags_trigger[p->flags.trigger]); 147 if(p->flags.reserved) 148 printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n", 149 p->flags.reserved); 150 151 } 152 break; 153 154 case ACPI_MADT_NMI_SRC: 155 { 156 struct acpi_table_nmi_src *p = 157 (struct acpi_table_nmi_src*) header; 158 printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n", 159 mps_inti_flags_polarity[p->flags.polarity], 160 mps_inti_flags_trigger[p->flags.trigger], p->global_irq); 161 } 162 break; 163 164 case ACPI_MADT_LAPIC_NMI: 165 { 166 struct acpi_table_lapic_nmi *p = 167 (struct acpi_table_lapic_nmi*) header; 168 printk(KERN_INFO PREFIX "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], p->lint); 172 } 173 break; 174 175 case ACPI_MADT_LAPIC_ADDR_OVR: 176 { 177 struct acpi_table_lapic_addr_ovr *p = 178 (struct acpi_table_lapic_addr_ovr*) header; 179 printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n", 180 (void *) (unsigned long) p->address); 181 } 182 break; 183 184 case ACPI_MADT_IOSAPIC: 185 { 186 struct acpi_table_iosapic *p = 187 (struct acpi_table_iosapic*) header; 188 printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", 189 p->id, (void *) (unsigned long) p->address, p->global_irq_base); 190 } 191 break; 192 193 case ACPI_MADT_LSAPIC: 194 { 195 struct acpi_table_lsapic *p = 196 (struct acpi_table_lsapic*) header; 197 printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", 198 p->acpi_id, p->id, p->eid, p->flags.enabled?"enabled":"disabled"); 199 } 200 break; 201 202 case ACPI_MADT_PLAT_INT_SRC: 203 { 204 struct acpi_table_plat_int_src *p = 205 (struct acpi_table_plat_int_src*) header; 206 printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", 207 mps_inti_flags_polarity[p->flags.polarity], 208 mps_inti_flags_trigger[p->flags.trigger], 209 p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); 210 } 211 break; 212 213 default: 214 printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n", 215 header->type); 216 break; 217 } 218 } 219 220 221 static int 222 acpi_table_compute_checksum ( 223 void *table_pointer, 224 unsigned long length) 225 { 226 u8 *p = (u8 *) table_pointer; 227 unsigned long remains = length; 228 unsigned long sum = 0; 229 230 if (!p || !length) 231 return -EINVAL; 232 233 while (remains--) 234 sum += *p++; 235 236 return (sum & 0xFF); 237 } 238 239 /* 240 * acpi_get_table_header_early() 241 * for acpi_blacklisted(), acpi_table_get_sdt() 242 */ 243 int __init 244 acpi_get_table_header_early ( 245 enum acpi_table_id id, 246 struct acpi_table_header **header) 247 { 248 unsigned int i; 249 enum acpi_table_id temp_id; 250 251 /* DSDT is different from the rest */ 252 if (id == ACPI_DSDT) 253 temp_id = ACPI_FADT; 254 else 255 temp_id = id; 256 257 /* Locate the table. */ 258 259 for (i = 0; i < sdt_count; i++) { 260 if (sdt_entry[i].id != temp_id) 261 continue; 262 *header = (void *) 263 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); 264 if (!*header) { 265 printk(KERN_WARNING PREFIX "Unable to map %s\n", 266 acpi_table_signatures[temp_id]); 267 return -ENODEV; 268 } 269 break; 270 } 271 272 if (!*header) { 273 printk(KERN_WARNING PREFIX "%s not present\n", 274 acpi_table_signatures[id]); 275 return -ENODEV; 276 } 277 278 /* Map the DSDT header via the pointer in the FADT */ 279 if (id == ACPI_DSDT) { 280 struct fadt_descriptor_rev2 *fadt = (struct fadt_descriptor_rev2 *) *header; 281 282 if (fadt->revision == 3 && fadt->Xdsdt) { 283 *header = (void *) __acpi_map_table(fadt->Xdsdt, 284 sizeof(struct acpi_table_header)); 285 } else if (fadt->V1_dsdt) { 286 *header = (void *) __acpi_map_table(fadt->V1_dsdt, 287 sizeof(struct acpi_table_header)); 288 } else 289 *header = NULL; 290 291 if (!*header) { 292 printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); 293 return -ENODEV; 294 } 295 } 296 297 return 0; 298 } 299 300 301 int __init 302 acpi_table_parse_madt_family ( 303 enum acpi_table_id id, 304 unsigned long madt_size, 305 int entry_id, 306 acpi_madt_entry_handler handler, 307 unsigned int max_entries) 308 { 309 void *madt = NULL; 310 acpi_table_entry_header *entry; 311 unsigned int count = 0; 312 unsigned long madt_end; 313 unsigned int i; 314 315 if (!handler) 316 return -EINVAL; 317 318 /* Locate the MADT (if exists). There should only be one. */ 319 320 for (i = 0; i < sdt_count; i++) { 321 if (sdt_entry[i].id != id) 322 continue; 323 madt = (void *) 324 __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); 325 if (!madt) { 326 printk(KERN_WARNING PREFIX "Unable to map %s\n", 327 acpi_table_signatures[id]); 328 return -ENODEV; 329 } 330 break; 331 } 332 333 if (!madt) { 334 printk(KERN_WARNING PREFIX "%s not present\n", 335 acpi_table_signatures[id]); 336 return -ENODEV; 337 } 338 339 madt_end = (unsigned long) madt + sdt_entry[i].size; 340 341 /* Parse all entries looking for a match. */ 342 343 entry = (acpi_table_entry_header *) 344 ((unsigned long) madt + madt_size); 345 346 while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) { 347 if (entry->type == entry_id && 348 (!max_entries || count++ < max_entries)) 349 if (handler(entry, madt_end)) 350 return -EINVAL; 351 352 entry = (acpi_table_entry_header *) 353 ((unsigned long) entry + entry->length); 354 } 355 if (max_entries && count > max_entries) { 356 printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of " 357 "%i found\n", acpi_table_signatures[id], entry_id, 358 count - max_entries, count); 359 } 360 361 return count; 362 } 363 364 365 int __init 366 acpi_table_parse_madt ( 367 enum acpi_madt_entry_id id, 368 acpi_madt_entry_handler handler, 369 unsigned int max_entries) 370 { 371 return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt), 372 id, handler, max_entries); 373 } 374 375 376 int __init 377 acpi_table_parse ( 378 enum acpi_table_id id, 379 acpi_table_handler handler) 380 { 381 int count = 0; 382 unsigned int i = 0; 383 384 if (!handler) 385 return -EINVAL; 386 387 for (i = 0; i < sdt_count; i++) { 388 if (sdt_entry[i].id != id) 389 continue; 390 count++; 391 if (count == 1) 392 handler(sdt_entry[i].pa, sdt_entry[i].size); 393 394 else 395 printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n", 396 count, acpi_table_signatures[id]); 397 } 398 399 return count; 400 } 401 402 403 static int __init 404 acpi_table_get_sdt ( 405 struct acpi_table_rsdp *rsdp) 406 { 407 struct acpi_table_header *header = NULL; 408 unsigned int i, id = 0; 409 410 if (!rsdp) 411 return -EINVAL; 412 413 /* First check XSDT (but only on ACPI 2.0-compatible systems) */ 414 415 if ((rsdp->revision >= 2) && 416 (((struct acpi20_table_rsdp*)rsdp)->xsdt_address)) { 417 418 struct acpi_table_xsdt *mapped_xsdt = NULL; 419 420 sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address; 421 422 /* map in just the header */ 423 header = (struct acpi_table_header *) 424 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); 425 426 if (!header) { 427 printk(KERN_WARNING PREFIX "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 "XSDT signature incorrect\n"); 442 return -ENODEV; 443 } 444 445 if (acpi_table_compute_checksum(header, header->length)) { 446 printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n"); 447 return -ENODEV; 448 } 449 450 sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3; 451 if (sdt_count > ACPI_MAX_TABLES) { 452 printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n", 453 (sdt_count - ACPI_MAX_TABLES)); 454 sdt_count = ACPI_MAX_TABLES; 455 } 456 457 for (i = 0; i < sdt_count; i++) 458 sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i]; 459 } 460 461 /* Then check RSDT */ 462 463 else if (rsdp->rsdt_address) { 464 465 struct acpi_table_rsdt *mapped_rsdt = NULL; 466 467 sdt_pa = rsdp->rsdt_address; 468 469 /* map in just the header */ 470 header = (struct acpi_table_header *) 471 __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); 472 if (!header) { 473 printk(KERN_WARNING PREFIX "Unable to map RSDT header\n"); 474 return -ENODEV; 475 } 476 477 /* remap in the entire table before processing */ 478 mapped_rsdt = (struct acpi_table_rsdt *) 479 __acpi_map_table(sdt_pa, header->length); 480 if (!mapped_rsdt) { 481 printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); 482 return -ENODEV; 483 } 484 header = &mapped_rsdt->header; 485 486 if (strncmp(header->signature, "RSDT", 4)) { 487 printk(KERN_WARNING PREFIX "RSDT signature incorrect\n"); 488 return -ENODEV; 489 } 490 491 if (acpi_table_compute_checksum(header, header->length)) { 492 printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n"); 493 return -ENODEV; 494 } 495 496 sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2; 497 if (sdt_count > ACPI_MAX_TABLES) { 498 printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n", 499 (sdt_count - ACPI_MAX_TABLES)); 500 sdt_count = ACPI_MAX_TABLES; 501 } 502 503 for (i = 0; i < sdt_count; i++) 504 sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; 505 } 506 507 else { 508 printk(KERN_WARNING PREFIX "No System Description Table (RSDT/XSDT) specified in RSDP\n"); 509 return -ENODEV; 510 } 511 512 acpi_table_print(header, sdt_pa); 513 514 for (i = 0; i < sdt_count; i++) { 515 516 /* map in just the header */ 517 header = (struct acpi_table_header *) 518 __acpi_map_table(sdt_entry[i].pa, 519 sizeof(struct acpi_table_header)); 520 if (!header) 521 continue; 522 523 /* remap in the entire table before processing */ 524 header = (struct acpi_table_header *) 525 __acpi_map_table(sdt_entry[i].pa, 526 header->length); 527 if (!header) 528 continue; 529 530 acpi_table_print(header, sdt_entry[i].pa); 531 532 if (acpi_table_compute_checksum(header, header->length)) { 533 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); 534 continue; 535 } 536 537 sdt_entry[i].size = header->length; 538 539 for (id = 0; id < ACPI_TABLE_COUNT; id++) { 540 if (!strncmp((char *) &header->signature, 541 acpi_table_signatures[id], 542 sizeof(header->signature))) { 543 sdt_entry[i].id = id; 544 } 545 } 546 } 547 548 /* 549 * The DSDT is *not* in the RSDT (why not? no idea.) but we want 550 * to print its info, because this is what people usually blacklist 551 * against. Unfortunately, we don't know the phys_addr, so just 552 * print 0. Maybe no one will notice. 553 */ 554 if(!acpi_get_table_header_early(ACPI_DSDT, &header)) 555 acpi_table_print(header, 0); 556 557 return 0; 558 } 559 560 /* 561 * acpi_table_init() 562 * 563 * find RSDP, find and checksum SDT/XSDT. 564 * checksum all tables, print SDT/XSDT 565 * 566 * result: sdt_entry[] is initialized 567 */ 568 569 int __init 570 acpi_table_init (void) 571 { 572 struct acpi_table_rsdp *rsdp = NULL; 573 unsigned long rsdp_phys = 0; 574 int result = 0; 575 576 /* Locate and map the Root System Description Table (RSDP) */ 577 578 rsdp_phys = acpi_find_rsdp(); 579 if (!rsdp_phys) { 580 printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); 581 return -ENODEV; 582 } 583 584 rsdp = (struct acpi_table_rsdp *) __va(rsdp_phys); 585 if (!rsdp) { 586 printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); 587 return -ENODEV; 588 } 589 590 printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", 591 rsdp->revision, rsdp->oem_id, (void *) rsdp_phys); 592 593 if (rsdp->revision < 2) 594 result = acpi_table_compute_checksum(rsdp, sizeof(struct acpi_table_rsdp)); 595 else 596 result = acpi_table_compute_checksum(rsdp, ((struct acpi20_table_rsdp *)rsdp)->length); 597 598 if (result) { 599 printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); 600 return -ENODEV; 601 } 602 603 /* Locate and map the System Description table (RSDT/XSDT) */ 604 605 if (acpi_table_get_sdt(rsdp)) 606 return -ENODEV; 607 608 return 0; 609 } 610