1 /****************************************************************************** 2 * 3 * Module Name: tbxface - Public interfaces to the ACPI subsystem 4 * ACPI table oriented interfaces 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #define __TBXFACE_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acnamesp.h" 50 #include "actables.h" 51 52 #define _COMPONENT ACPI_TABLES 53 ACPI_MODULE_NAME ("tbxface") 54 55 /* Local prototypes */ 56 57 static ACPI_STATUS 58 AcpiTbLoadNamespace ( 59 void); 60 61 62 /******************************************************************************* 63 * 64 * FUNCTION: AcpiAllocateRootTable 65 * 66 * PARAMETERS: InitialTableCount - Size of InitialTableArray, in number of 67 * ACPI_TABLE_DESC structures 68 * 69 * RETURN: Status 70 * 71 * DESCRIPTION: Allocate a root table array. Used by iASL compiler and 72 * AcpiInitializeTables. 73 * 74 ******************************************************************************/ 75 76 ACPI_STATUS 77 AcpiAllocateRootTable ( 78 UINT32 InitialTableCount) 79 { 80 81 AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; 82 AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE; 83 84 return (AcpiTbResizeRootTableList ()); 85 } 86 87 88 /******************************************************************************* 89 * 90 * FUNCTION: AcpiInitializeTables 91 * 92 * PARAMETERS: InitialTableArray - Pointer to an array of pre-allocated 93 * ACPI_TABLE_DESC structures. If NULL, the 94 * array is dynamically allocated. 95 * InitialTableCount - Size of InitialTableArray, in number of 96 * ACPI_TABLE_DESC structures 97 * AllowRealloc - Flag to tell Table Manager if resize of 98 * pre-allocated array is allowed. Ignored 99 * if InitialTableArray is NULL. 100 * 101 * RETURN: Status 102 * 103 * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. 104 * 105 * NOTE: Allows static allocation of the initial table array in order 106 * to avoid the use of dynamic memory in confined environments 107 * such as the kernel boot sequence where it may not be available. 108 * 109 * If the host OS memory managers are initialized, use NULL for 110 * InitialTableArray, and the table will be dynamically allocated. 111 * 112 ******************************************************************************/ 113 114 ACPI_STATUS 115 AcpiInitializeTables ( 116 ACPI_TABLE_DESC *InitialTableArray, 117 UINT32 InitialTableCount, 118 BOOLEAN AllowResize) 119 { 120 ACPI_PHYSICAL_ADDRESS RsdpAddress; 121 ACPI_STATUS Status; 122 123 124 ACPI_FUNCTION_TRACE (AcpiInitializeTables); 125 126 127 /* 128 * Set up the Root Table Array 129 * Allocate the table array if requested 130 */ 131 if (!InitialTableArray) 132 { 133 Status = AcpiAllocateRootTable (InitialTableCount); 134 if (ACPI_FAILURE (Status)) 135 { 136 return_ACPI_STATUS (Status); 137 } 138 } 139 else 140 { 141 /* Root Table Array has been statically allocated by the host */ 142 143 ACPI_MEMSET (InitialTableArray, 0, 144 (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC)); 145 146 AcpiGbl_RootTableList.Tables = InitialTableArray; 147 AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; 148 AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN; 149 if (AllowResize) 150 { 151 AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE; 152 } 153 } 154 155 /* Get the address of the RSDP */ 156 157 RsdpAddress = AcpiOsGetRootPointer (); 158 if (!RsdpAddress) 159 { 160 return_ACPI_STATUS (AE_NOT_FOUND); 161 } 162 163 /* 164 * Get the root table (RSDT or XSDT) and extract all entries to the local 165 * Root Table Array. This array contains the information of the RSDT/XSDT 166 * in a common, more useable format. 167 */ 168 Status = AcpiTbParseRootTable (RsdpAddress); 169 return_ACPI_STATUS (Status); 170 } 171 172 ACPI_EXPORT_SYMBOL (AcpiInitializeTables) 173 174 175 /******************************************************************************* 176 * 177 * FUNCTION: AcpiReallocateRootTable 178 * 179 * PARAMETERS: None 180 * 181 * RETURN: Status 182 * 183 * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the 184 * root list from the previously provided scratch area. Should 185 * be called once dynamic memory allocation is available in the 186 * kernel 187 * 188 ******************************************************************************/ 189 190 ACPI_STATUS 191 AcpiReallocateRootTable ( 192 void) 193 { 194 ACPI_TABLE_DESC *Tables; 195 ACPI_SIZE NewSize; 196 ACPI_SIZE CurrentSize; 197 198 199 ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); 200 201 202 /* 203 * Only reallocate the root table if the host provided a static buffer 204 * for the table array in the call to AcpiInitializeTables. 205 */ 206 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) 207 { 208 return_ACPI_STATUS (AE_SUPPORT); 209 } 210 211 /* 212 * Get the current size of the root table and add the default 213 * increment to create the new table size. 214 */ 215 CurrentSize = (ACPI_SIZE) 216 AcpiGbl_RootTableList.CurrentTableCount * sizeof (ACPI_TABLE_DESC); 217 218 NewSize = CurrentSize + 219 (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof (ACPI_TABLE_DESC)); 220 221 /* Create new array and copy the old array */ 222 223 Tables = ACPI_ALLOCATE_ZEROED (NewSize); 224 if (!Tables) 225 { 226 return_ACPI_STATUS (AE_NO_MEMORY); 227 } 228 229 ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, CurrentSize); 230 231 /* 232 * Update the root table descriptor. The new size will be the current 233 * number of tables plus the increment, independent of the reserved 234 * size of the original table list. 235 */ 236 AcpiGbl_RootTableList.Tables = Tables; 237 AcpiGbl_RootTableList.MaxTableCount = 238 AcpiGbl_RootTableList.CurrentTableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT; 239 AcpiGbl_RootTableList.Flags = 240 ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; 241 242 return_ACPI_STATUS (AE_OK); 243 } 244 245 ACPI_EXPORT_SYMBOL (AcpiReallocateRootTable) 246 247 248 /******************************************************************************* 249 * 250 * FUNCTION: AcpiGetTableHeader 251 * 252 * PARAMETERS: Signature - ACPI signature of needed table 253 * Instance - Which instance (for SSDTs) 254 * OutTableHeader - The pointer to the table header to fill 255 * 256 * RETURN: Status and pointer to mapped table header 257 * 258 * DESCRIPTION: Finds an ACPI table header. 259 * 260 ******************************************************************************/ 261 262 ACPI_STATUS 263 AcpiGetTableHeader ( 264 ACPI_CONST_STRING Signature, 265 UINT32 Instance, 266 ACPI_TABLE_HEADER *OutTableHeader) 267 { 268 UINT32 i; 269 UINT32 j; 270 ACPI_TABLE_HEADER *Header; 271 ACPI_STRING USignature = __UNCONST(Signature); 272 273 /* Parameter validation */ 274 275 if (!Signature || !OutTableHeader) 276 { 277 return (AE_BAD_PARAMETER); 278 } 279 280 /* Walk the root table list */ 281 282 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 283 { 284 if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 285 USignature)) 286 { 287 continue; 288 } 289 290 if (++j < Instance) 291 { 292 continue; 293 } 294 295 if (!AcpiGbl_RootTableList.Tables[i].Pointer) 296 { 297 if ((AcpiGbl_RootTableList.Tables[i].Flags & 298 ACPI_TABLE_ORIGIN_MASK) == 299 ACPI_TABLE_ORIGIN_MAPPED) 300 { 301 Header = AcpiOsMapMemory ( 302 AcpiGbl_RootTableList.Tables[i].Address, 303 sizeof (ACPI_TABLE_HEADER)); 304 if (!Header) 305 { 306 return AE_NO_MEMORY; 307 } 308 309 ACPI_MEMCPY (OutTableHeader, Header, sizeof(ACPI_TABLE_HEADER)); 310 AcpiOsUnmapMemory (Header, sizeof(ACPI_TABLE_HEADER)); 311 } 312 else 313 { 314 return AE_NOT_FOUND; 315 } 316 } 317 else 318 { 319 ACPI_MEMCPY (OutTableHeader, 320 AcpiGbl_RootTableList.Tables[i].Pointer, 321 sizeof(ACPI_TABLE_HEADER)); 322 } 323 324 return (AE_OK); 325 } 326 327 return (AE_NOT_FOUND); 328 } 329 330 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader) 331 332 333 /******************************************************************************* 334 * 335 * FUNCTION: AcpiGetTable 336 * 337 * PARAMETERS: Signature - ACPI signature of needed table 338 * Instance - Which instance (for SSDTs) 339 * OutTable - Where the pointer to the table is returned 340 * 341 * RETURN: Status and pointer to table 342 * 343 * DESCRIPTION: Finds and verifies an ACPI table. 344 * 345 ******************************************************************************/ 346 347 ACPI_STATUS 348 AcpiGetTable ( 349 ACPI_CONST_STRING Signature, 350 UINT32 Instance, 351 ACPI_TABLE_HEADER **OutTable) 352 { 353 UINT32 i; 354 UINT32 j; 355 ACPI_STATUS Status; 356 ACPI_STRING USignature = __UNCONST(Signature); 357 358 /* Parameter validation */ 359 360 if (!Signature || !OutTable) 361 { 362 return (AE_BAD_PARAMETER); 363 } 364 365 /* Walk the root table list */ 366 367 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 368 { 369 if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 370 USignature)) 371 { 372 continue; 373 } 374 375 if (++j < Instance) 376 { 377 continue; 378 } 379 380 Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); 381 if (ACPI_SUCCESS (Status)) 382 { 383 *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer; 384 } 385 386 return (Status); 387 } 388 389 return (AE_NOT_FOUND); 390 } 391 392 ACPI_EXPORT_SYMBOL (AcpiGetTable) 393 394 395 /******************************************************************************* 396 * 397 * FUNCTION: AcpiGetTableByIndex 398 * 399 * PARAMETERS: TableIndex - Table index 400 * Table - Where the pointer to the table is returned 401 * 402 * RETURN: Status and pointer to the table 403 * 404 * DESCRIPTION: Obtain a table by an index into the global table list. 405 * 406 ******************************************************************************/ 407 408 ACPI_STATUS 409 AcpiGetTableByIndex ( 410 UINT32 TableIndex, 411 ACPI_TABLE_HEADER **Table) 412 { 413 ACPI_STATUS Status; 414 415 416 ACPI_FUNCTION_TRACE (AcpiGetTableByIndex); 417 418 419 /* Parameter validation */ 420 421 if (!Table) 422 { 423 return_ACPI_STATUS (AE_BAD_PARAMETER); 424 } 425 426 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 427 428 /* Validate index */ 429 430 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) 431 { 432 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 433 return_ACPI_STATUS (AE_BAD_PARAMETER); 434 } 435 436 if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer) 437 { 438 /* Table is not mapped, map it */ 439 440 Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[TableIndex]); 441 if (ACPI_FAILURE (Status)) 442 { 443 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 444 return_ACPI_STATUS (Status); 445 } 446 } 447 448 *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer; 449 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 450 return_ACPI_STATUS (AE_OK); 451 } 452 453 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) 454 455 456 /******************************************************************************* 457 * 458 * FUNCTION: AcpiTbLoadNamespace 459 * 460 * PARAMETERS: None 461 * 462 * RETURN: Status 463 * 464 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 465 * the RSDT/XSDT. 466 * 467 ******************************************************************************/ 468 469 static ACPI_STATUS 470 AcpiTbLoadNamespace ( 471 void) 472 { 473 ACPI_STATUS Status; 474 UINT32 i; 475 ACPI_TABLE_HEADER *NewDsdt; 476 477 478 ACPI_FUNCTION_TRACE (TbLoadNamespace); 479 480 481 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 482 483 /* 484 * Load the namespace. The DSDT is required, but any SSDT and 485 * PSDT tables are optional. Verify the DSDT. 486 */ 487 if (!AcpiGbl_RootTableList.CurrentTableCount || 488 !ACPI_COMPARE_NAME ( 489 &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), 490 ACPI_SIG_DSDT) || 491 ACPI_FAILURE (AcpiTbVerifyTable ( 492 &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) 493 { 494 Status = AE_NO_ACPI_TABLES; 495 goto UnlockAndExit; 496 } 497 498 /* 499 * Save the DSDT pointer for simple access. This is the mapped memory 500 * address. We must take care here because the address of the .Tables 501 * array can change dynamically as tables are loaded at run-time. Note: 502 * .Pointer field is not validated until after call to AcpiTbVerifyTable. 503 */ 504 AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; 505 506 /* 507 * Optionally copy the entire DSDT to local memory (instead of simply 508 * mapping it.) There are some BIOSs that corrupt or replace the original 509 * DSDT, creating the need for this option. Default is FALSE, do not copy 510 * the DSDT. 511 */ 512 if (AcpiGbl_CopyDsdtLocally) 513 { 514 NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); 515 if (NewDsdt) 516 { 517 AcpiGbl_DSDT = NewDsdt; 518 } 519 } 520 521 /* 522 * Save the original DSDT header for detection of table corruption 523 * and/or replacement of the DSDT from outside the OS. 524 */ 525 ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, 526 sizeof (ACPI_TABLE_HEADER)); 527 528 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 529 530 /* Load and parse tables */ 531 532 Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); 533 if (ACPI_FAILURE (Status)) 534 { 535 return_ACPI_STATUS (Status); 536 } 537 538 /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 539 540 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 541 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 542 { 543 if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 544 ACPI_SIG_SSDT) && 545 !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 546 ACPI_SIG_PSDT)) || 547 ACPI_FAILURE (AcpiTbVerifyTable ( 548 &AcpiGbl_RootTableList.Tables[i]))) 549 { 550 continue; 551 } 552 553 /* Ignore errors while loading tables, get as many as possible */ 554 555 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 556 (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); 557 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 558 } 559 560 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); 561 562 UnlockAndExit: 563 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 564 return_ACPI_STATUS (Status); 565 } 566 567 568 /******************************************************************************* 569 * 570 * FUNCTION: AcpiLoadTables 571 * 572 * PARAMETERS: None 573 * 574 * RETURN: Status 575 * 576 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 577 * 578 ******************************************************************************/ 579 580 ACPI_STATUS 581 AcpiLoadTables ( 582 void) 583 { 584 ACPI_STATUS Status; 585 586 587 ACPI_FUNCTION_TRACE (AcpiLoadTables); 588 589 590 /* Load the namespace from the tables */ 591 592 Status = AcpiTbLoadNamespace (); 593 if (ACPI_FAILURE (Status)) 594 { 595 ACPI_EXCEPTION ((AE_INFO, Status, 596 "While loading namespace from ACPI tables")); 597 } 598 599 return_ACPI_STATUS (Status); 600 } 601 602 ACPI_EXPORT_SYMBOL (AcpiLoadTables) 603 604 605 /******************************************************************************* 606 * 607 * FUNCTION: AcpiInstallTableHandler 608 * 609 * PARAMETERS: Handler - Table event handler 610 * Context - Value passed to the handler on each event 611 * 612 * RETURN: Status 613 * 614 * DESCRIPTION: Install table event handler 615 * 616 ******************************************************************************/ 617 618 ACPI_STATUS 619 AcpiInstallTableHandler ( 620 ACPI_TABLE_HANDLER Handler, 621 void *Context) 622 { 623 ACPI_STATUS Status; 624 625 626 ACPI_FUNCTION_TRACE (AcpiInstallTableHandler); 627 628 629 if (!Handler) 630 { 631 return_ACPI_STATUS (AE_BAD_PARAMETER); 632 } 633 634 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 635 if (ACPI_FAILURE (Status)) 636 { 637 return_ACPI_STATUS (Status); 638 } 639 640 /* Don't allow more than one handler */ 641 642 if (AcpiGbl_TableHandler) 643 { 644 Status = AE_ALREADY_EXISTS; 645 goto Cleanup; 646 } 647 648 /* Install the handler */ 649 650 AcpiGbl_TableHandler = Handler; 651 AcpiGbl_TableHandlerContext = Context; 652 653 Cleanup: 654 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 655 return_ACPI_STATUS (Status); 656 } 657 658 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler) 659 660 661 /******************************************************************************* 662 * 663 * FUNCTION: AcpiRemoveTableHandler 664 * 665 * PARAMETERS: Handler - Table event handler that was installed 666 * previously. 667 * 668 * RETURN: Status 669 * 670 * DESCRIPTION: Remove table event handler 671 * 672 ******************************************************************************/ 673 674 ACPI_STATUS 675 AcpiRemoveTableHandler ( 676 ACPI_TABLE_HANDLER Handler) 677 { 678 ACPI_STATUS Status; 679 680 681 ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler); 682 683 684 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 685 if (ACPI_FAILURE (Status)) 686 { 687 return_ACPI_STATUS (Status); 688 } 689 690 /* Make sure that the installed handler is the same */ 691 692 if (!Handler || 693 Handler != AcpiGbl_TableHandler) 694 { 695 Status = AE_BAD_PARAMETER; 696 goto Cleanup; 697 } 698 699 /* Remove the handler */ 700 701 AcpiGbl_TableHandler = NULL; 702 703 Cleanup: 704 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 705 return_ACPI_STATUS (Status); 706 } 707 708 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler) 709 710