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 * NOTE: Caller is responsible in unmapping the header with 261 * AcpiOsUnmapMemory 262 * 263 ******************************************************************************/ 264 265 ACPI_STATUS 266 AcpiGetTableHeader ( 267 char *Signature, 268 UINT32 Instance, 269 ACPI_TABLE_HEADER *OutTableHeader) 270 { 271 UINT32 i; 272 UINT32 j; 273 ACPI_TABLE_HEADER *Header; 274 275 276 /* Parameter validation */ 277 278 if (!Signature || !OutTableHeader) 279 { 280 return (AE_BAD_PARAMETER); 281 } 282 283 /* Walk the root table list */ 284 285 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 286 { 287 if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 288 Signature)) 289 { 290 continue; 291 } 292 293 if (++j < Instance) 294 { 295 continue; 296 } 297 298 if (!AcpiGbl_RootTableList.Tables[i].Pointer) 299 { 300 if ((AcpiGbl_RootTableList.Tables[i].Flags & 301 ACPI_TABLE_ORIGIN_MASK) == 302 ACPI_TABLE_ORIGIN_MAPPED) 303 { 304 Header = AcpiOsMapMemory ( 305 AcpiGbl_RootTableList.Tables[i].Address, 306 sizeof (ACPI_TABLE_HEADER)); 307 if (!Header) 308 { 309 return AE_NO_MEMORY; 310 } 311 312 ACPI_MEMCPY (OutTableHeader, Header, sizeof(ACPI_TABLE_HEADER)); 313 AcpiOsUnmapMemory (Header, sizeof(ACPI_TABLE_HEADER)); 314 } 315 else 316 { 317 return AE_NOT_FOUND; 318 } 319 } 320 else 321 { 322 ACPI_MEMCPY (OutTableHeader, 323 AcpiGbl_RootTableList.Tables[i].Pointer, 324 sizeof(ACPI_TABLE_HEADER)); 325 } 326 327 return (AE_OK); 328 } 329 330 return (AE_NOT_FOUND); 331 } 332 333 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader) 334 335 336 /******************************************************************************* 337 * 338 * FUNCTION: AcpiGetTable 339 * 340 * PARAMETERS: Signature - ACPI signature of needed table 341 * Instance - Which instance (for SSDTs) 342 * OutTable - Where the pointer to the table is returned 343 * 344 * RETURN: Status and pointer to table 345 * 346 * DESCRIPTION: Finds and verifies an ACPI table. 347 * 348 ******************************************************************************/ 349 350 ACPI_STATUS 351 AcpiGetTable ( 352 char *Signature, 353 UINT32 Instance, 354 ACPI_TABLE_HEADER **OutTable) 355 { 356 UINT32 i; 357 UINT32 j; 358 ACPI_STATUS Status; 359 360 361 /* Parameter validation */ 362 363 if (!Signature || !OutTable) 364 { 365 return (AE_BAD_PARAMETER); 366 } 367 368 /* Walk the root table list */ 369 370 for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 371 { 372 if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 373 Signature)) 374 { 375 continue; 376 } 377 378 if (++j < Instance) 379 { 380 continue; 381 } 382 383 Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); 384 if (ACPI_SUCCESS (Status)) 385 { 386 *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer; 387 } 388 389 return (Status); 390 } 391 392 return (AE_NOT_FOUND); 393 } 394 395 ACPI_EXPORT_SYMBOL (AcpiGetTable) 396 397 398 /******************************************************************************* 399 * 400 * FUNCTION: AcpiGetTableByIndex 401 * 402 * PARAMETERS: TableIndex - Table index 403 * Table - Where the pointer to the table is returned 404 * 405 * RETURN: Status and pointer to the table 406 * 407 * DESCRIPTION: Obtain a table by an index into the global table list. 408 * 409 ******************************************************************************/ 410 411 ACPI_STATUS 412 AcpiGetTableByIndex ( 413 UINT32 TableIndex, 414 ACPI_TABLE_HEADER **Table) 415 { 416 ACPI_STATUS Status; 417 418 419 ACPI_FUNCTION_TRACE (AcpiGetTableByIndex); 420 421 422 /* Parameter validation */ 423 424 if (!Table) 425 { 426 return_ACPI_STATUS (AE_BAD_PARAMETER); 427 } 428 429 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 430 431 /* Validate index */ 432 433 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) 434 { 435 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 436 return_ACPI_STATUS (AE_BAD_PARAMETER); 437 } 438 439 if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer) 440 { 441 /* Table is not mapped, map it */ 442 443 Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[TableIndex]); 444 if (ACPI_FAILURE (Status)) 445 { 446 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 447 return_ACPI_STATUS (Status); 448 } 449 } 450 451 *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer; 452 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 453 return_ACPI_STATUS (AE_OK); 454 } 455 456 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) 457 458 459 /******************************************************************************* 460 * 461 * FUNCTION: AcpiTbLoadNamespace 462 * 463 * PARAMETERS: None 464 * 465 * RETURN: Status 466 * 467 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 468 * the RSDT/XSDT. 469 * 470 ******************************************************************************/ 471 472 static ACPI_STATUS 473 AcpiTbLoadNamespace ( 474 void) 475 { 476 ACPI_STATUS Status; 477 UINT32 i; 478 ACPI_TABLE_HEADER *NewDsdt; 479 480 481 ACPI_FUNCTION_TRACE (TbLoadNamespace); 482 483 484 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 485 486 /* 487 * Load the namespace. The DSDT is required, but any SSDT and 488 * PSDT tables are optional. Verify the DSDT. 489 */ 490 if (!AcpiGbl_RootTableList.CurrentTableCount || 491 !ACPI_COMPARE_NAME ( 492 &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), 493 ACPI_SIG_DSDT) || 494 ACPI_FAILURE (AcpiTbVerifyTable ( 495 &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) 496 { 497 Status = AE_NO_ACPI_TABLES; 498 goto UnlockAndExit; 499 } 500 501 /* 502 * Save the DSDT pointer for simple access. This is the mapped memory 503 * address. We must take care here because the address of the .Tables 504 * array can change dynamically as tables are loaded at run-time. Note: 505 * .Pointer field is not validated until after call to AcpiTbVerifyTable. 506 */ 507 AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; 508 509 /* 510 * Optionally copy the entire DSDT to local memory (instead of simply 511 * mapping it.) There are some BIOSs that corrupt or replace the original 512 * DSDT, creating the need for this option. Default is FALSE, do not copy 513 * the DSDT. 514 */ 515 if (AcpiGbl_CopyDsdtLocally) 516 { 517 NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); 518 if (NewDsdt) 519 { 520 AcpiGbl_DSDT = NewDsdt; 521 } 522 } 523 524 /* 525 * Save the original DSDT header for detection of table corruption 526 * and/or replacement of the DSDT from outside the OS. 527 */ 528 ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, 529 sizeof (ACPI_TABLE_HEADER)); 530 531 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 532 533 /* Load and parse tables */ 534 535 Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); 536 if (ACPI_FAILURE (Status)) 537 { 538 return_ACPI_STATUS (Status); 539 } 540 541 /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 542 543 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 544 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 545 { 546 if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 547 ACPI_SIG_SSDT) && 548 !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 549 ACPI_SIG_PSDT)) || 550 ACPI_FAILURE (AcpiTbVerifyTable ( 551 &AcpiGbl_RootTableList.Tables[i]))) 552 { 553 continue; 554 } 555 556 /* Ignore errors while loading tables, get as many as possible */ 557 558 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 559 (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); 560 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 561 } 562 563 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); 564 565 UnlockAndExit: 566 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 567 return_ACPI_STATUS (Status); 568 } 569 570 571 /******************************************************************************* 572 * 573 * FUNCTION: AcpiLoadTables 574 * 575 * PARAMETERS: None 576 * 577 * RETURN: Status 578 * 579 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 580 * 581 ******************************************************************************/ 582 583 ACPI_STATUS 584 AcpiLoadTables ( 585 void) 586 { 587 ACPI_STATUS Status; 588 589 590 ACPI_FUNCTION_TRACE (AcpiLoadTables); 591 592 593 /* Load the namespace from the tables */ 594 595 Status = AcpiTbLoadNamespace (); 596 if (ACPI_FAILURE (Status)) 597 { 598 ACPI_EXCEPTION ((AE_INFO, Status, 599 "While loading namespace from ACPI tables")); 600 } 601 602 return_ACPI_STATUS (Status); 603 } 604 605 ACPI_EXPORT_SYMBOL (AcpiLoadTables) 606 607 608 /******************************************************************************* 609 * 610 * FUNCTION: AcpiInstallTableHandler 611 * 612 * PARAMETERS: Handler - Table event handler 613 * Context - Value passed to the handler on each event 614 * 615 * RETURN: Status 616 * 617 * DESCRIPTION: Install table event handler 618 * 619 ******************************************************************************/ 620 621 ACPI_STATUS 622 AcpiInstallTableHandler ( 623 ACPI_TABLE_HANDLER Handler, 624 void *Context) 625 { 626 ACPI_STATUS Status; 627 628 629 ACPI_FUNCTION_TRACE (AcpiInstallTableHandler); 630 631 632 if (!Handler) 633 { 634 return_ACPI_STATUS (AE_BAD_PARAMETER); 635 } 636 637 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 638 if (ACPI_FAILURE (Status)) 639 { 640 return_ACPI_STATUS (Status); 641 } 642 643 /* Don't allow more than one handler */ 644 645 if (AcpiGbl_TableHandler) 646 { 647 Status = AE_ALREADY_EXISTS; 648 goto Cleanup; 649 } 650 651 /* Install the handler */ 652 653 AcpiGbl_TableHandler = Handler; 654 AcpiGbl_TableHandlerContext = Context; 655 656 Cleanup: 657 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 658 return_ACPI_STATUS (Status); 659 } 660 661 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler) 662 663 664 /******************************************************************************* 665 * 666 * FUNCTION: AcpiRemoveTableHandler 667 * 668 * PARAMETERS: Handler - Table event handler that was installed 669 * previously. 670 * 671 * RETURN: Status 672 * 673 * DESCRIPTION: Remove table event handler 674 * 675 ******************************************************************************/ 676 677 ACPI_STATUS 678 AcpiRemoveTableHandler ( 679 ACPI_TABLE_HANDLER Handler) 680 { 681 ACPI_STATUS Status; 682 683 684 ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler); 685 686 687 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 688 if (ACPI_FAILURE (Status)) 689 { 690 return_ACPI_STATUS (Status); 691 } 692 693 /* Make sure that the installed handler is the same */ 694 695 if (!Handler || 696 Handler != AcpiGbl_TableHandler) 697 { 698 Status = AE_BAD_PARAMETER; 699 goto Cleanup; 700 } 701 702 /* Remove the handler */ 703 704 AcpiGbl_TableHandler = NULL; 705 706 Cleanup: 707 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 708 return_ACPI_STATUS (Status); 709 } 710 711 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler) 712 713