1 /******************************************************************************
   2  *
   3  * Module Name: tbinstal - ACPI table installation and removal
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #define __TBINSTAL_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acnamesp.h"
  50 #include "actables.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_TABLES
  54         ACPI_MODULE_NAME    ("tbinstal")
  55 
  56 
  57 /******************************************************************************
  58  *
  59  * FUNCTION:    AcpiTbVerifyTable
  60  *
  61  * PARAMETERS:  TableDesc           - table
  62  *
  63  * RETURN:      Status
  64  *
  65  * DESCRIPTION: this function is called to verify and map table
  66  *
  67  *****************************************************************************/
  68 
  69 ACPI_STATUS
  70 AcpiTbVerifyTable (
  71     ACPI_TABLE_DESC         *TableDesc)
  72 {
  73     ACPI_STATUS             Status = AE_OK;
  74 
  75 
  76     ACPI_FUNCTION_TRACE (TbVerifyTable);
  77 
  78 
  79     /* Map the table if necessary */
  80 
  81     if (!TableDesc->Pointer)
  82     {
  83         if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
  84             ACPI_TABLE_ORIGIN_MAPPED)
  85         {
  86             TableDesc->Pointer = AcpiOsMapMemory (
  87                 TableDesc->Address, TableDesc->Length);
  88         }
  89 
  90         if (!TableDesc->Pointer)
  91         {
  92             return_ACPI_STATUS (AE_NO_MEMORY);
  93         }
  94     }
  95 
  96     /* Always calculate checksum, ignore bad checksum if requested */
  97 
  98     Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
  99 
 100     return_ACPI_STATUS (Status);
 101 }
 102 
 103 
 104 /*******************************************************************************
 105  *
 106  * FUNCTION:    AcpiTbAddTable
 107  *
 108  * PARAMETERS:  TableDesc           - Table descriptor
 109  *              TableIndex          - Where the table index is returned
 110  *
 111  * RETURN:      Status
 112  *
 113  * DESCRIPTION: This function is called to add an ACPI table. It is used to
 114  *              dynamically load tables via the Load and LoadTable AML
 115  *              operators.
 116  *
 117  ******************************************************************************/
 118 
 119 ACPI_STATUS
 120 AcpiTbAddTable (
 121     ACPI_TABLE_DESC         *TableDesc,
 122     UINT32                  *TableIndex)
 123 {
 124     UINT32                  i;
 125     ACPI_STATUS             Status = AE_OK;
 126 
 127 
 128     ACPI_FUNCTION_TRACE (TbAddTable);
 129 
 130 
 131     if (!TableDesc->Pointer)
 132     {
 133         Status = AcpiTbVerifyTable (TableDesc);
 134         if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
 135         {
 136             return_ACPI_STATUS (Status);
 137         }
 138     }
 139 
 140     /*
 141      * Validate the incoming table signature.
 142      *
 143      * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
 144      * 2) We added support for OEMx tables, signature "OEM".
 145      * 3) Valid tables were encountered with a null signature, so we just
 146      *    gave up on validating the signature, (05/2008).
 147      * 4) We encountered non-AML tables such as the MADT, which caused
 148      *    interpreter errors and kernel faults. So now, we once again allow
 149      *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
 150      */
 151     if ((TableDesc->Pointer->Signature[0] != 0x00) &&
 152        (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
 153        (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
 154     {
 155         ACPI_BIOS_ERROR ((AE_INFO,
 156             "Table has invalid signature [%4.4s] (0x%8.8X), "
 157             "must be SSDT or OEMx",
 158             AcpiUtValidAcpiName (TableDesc->Pointer->Signature) ?
 159                 TableDesc->Pointer->Signature : "????",
 160             *(UINT32 *) TableDesc->Pointer->Signature));
 161 
 162         return_ACPI_STATUS (AE_BAD_SIGNATURE);
 163     }
 164 
 165     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 166 
 167     /* Check if table is already registered */
 168 
 169     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
 170     {
 171         if (!AcpiGbl_RootTableList.Tables[i].Pointer)
 172         {
 173             Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
 174             if (ACPI_FAILURE (Status) ||
 175                 !AcpiGbl_RootTableList.Tables[i].Pointer)
 176             {
 177                 continue;
 178             }
 179         }
 180 
 181         /*
 182          * Check for a table match on the entire table length,
 183          * not just the header.
 184          */
 185         if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
 186         {
 187             continue;
 188         }
 189 
 190         if (ACPI_MEMCMP (TableDesc->Pointer,
 191                 AcpiGbl_RootTableList.Tables[i].Pointer,
 192                 AcpiGbl_RootTableList.Tables[i].Length))
 193         {
 194             continue;
 195         }
 196 
 197         /*
 198          * Note: the current mechanism does not unregister a table if it is
 199          * dynamically unloaded. The related namespace entries are deleted,
 200          * but the table remains in the root table list.
 201          *
 202          * The assumption here is that the number of different tables that
 203          * will be loaded is actually small, and there is minimal overhead
 204          * in just keeping the table in case it is needed again.
 205          *
 206          * If this assumption changes in the future (perhaps on large
 207          * machines with many table load/unload operations), tables will
 208          * need to be unregistered when they are unloaded, and slots in the
 209          * root table list should be reused when empty.
 210          */
 211 
 212         /*
 213          * Table is already registered.
 214          * We can delete the table that was passed as a parameter.
 215          */
 216         AcpiTbDeleteTable (TableDesc);
 217         *TableIndex = i;
 218 
 219         if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
 220         {
 221             /* Table is still loaded, this is an error */
 222 
 223             Status = AE_ALREADY_EXISTS;
 224             goto Release;
 225         }
 226         else
 227         {
 228             /* Table was unloaded, allow it to be reloaded */
 229 
 230             TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
 231             TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
 232             Status = AE_OK;
 233             goto PrintHeader;
 234         }
 235     }
 236 
 237     /*
 238      * ACPI Table Override:
 239      * Allow the host to override dynamically loaded tables.
 240      * NOTE: the table is fully mapped at this point, and the mapping will
 241      * be deleted by TbTableOverride if the table is actually overridden.
 242      */
 243     (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc);
 244 
 245     /* Add the table to the global root table list */
 246 
 247     Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
 248                 TableDesc->Length, TableDesc->Flags, TableIndex);
 249     if (ACPI_FAILURE (Status))
 250     {
 251         goto Release;
 252     }
 253 
 254 PrintHeader:
 255     AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
 256 
 257 Release:
 258     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 259     return_ACPI_STATUS (Status);
 260 }
 261 
 262 
 263 /*******************************************************************************
 264  *
 265  * FUNCTION:    AcpiTbTableOverride
 266  *
 267  * PARAMETERS:  TableHeader         - Header for the original table
 268  *              TableDesc           - Table descriptor initialized for the
 269  *                                    original table. May or may not be mapped.
 270  *
 271  * RETURN:      Pointer to the entire new table. NULL if table not overridden.
 272  *              If overridden, installs the new table within the input table
 273  *              descriptor.
 274  *
 275  * DESCRIPTION: Attempt table override by calling the OSL override functions.
 276  *              Note: If the table is overridden, then the entire new table
 277  *              is mapped and returned by this function.
 278  *
 279  ******************************************************************************/
 280 
 281 ACPI_TABLE_HEADER *
 282 AcpiTbTableOverride (
 283     ACPI_TABLE_HEADER       *TableHeader,
 284     ACPI_TABLE_DESC         *TableDesc)
 285 {
 286     ACPI_STATUS             Status;
 287     ACPI_TABLE_HEADER       *NewTable = NULL;
 288     ACPI_PHYSICAL_ADDRESS   NewAddress = 0;
 289     UINT32                  NewTableLength = 0;
 290     UINT8                   NewFlags;
 291     char                    *OverrideType;
 292 
 293 
 294     /* (1) Attempt logical override (returns a logical address) */
 295 
 296     Status = AcpiOsTableOverride (TableHeader, &NewTable);
 297     if (ACPI_SUCCESS (Status) && NewTable)
 298     {
 299         NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable);
 300         NewTableLength = NewTable->Length;
 301         NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE;
 302         OverrideType = "Logical";
 303         goto FinishOverride;
 304     }
 305 
 306     /* (2) Attempt physical override (returns a physical address) */
 307 
 308     Status = AcpiOsPhysicalTableOverride (TableHeader,
 309         &NewAddress, &NewTableLength);
 310     if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength)
 311     {
 312         /* Map the entire new table */
 313 
 314         NewTable = AcpiOsMapMemory (NewAddress, NewTableLength);
 315         if (!NewTable)
 316         {
 317             ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
 318                 "%4.4s %p Attempted physical table override failed",
 319                 TableHeader->Signature,
 320                 ACPI_CAST_PTR (void, TableDesc->Address)));
 321             return (NULL);
 322         }
 323 
 324         OverrideType = "Physical";
 325         NewFlags = ACPI_TABLE_ORIGIN_MAPPED;
 326         goto FinishOverride;
 327     }
 328 
 329     return (NULL); /* There was no override */
 330 
 331 
 332 FinishOverride:
 333 
 334     ACPI_INFO ((AE_INFO,
 335         "%4.4s %p %s table override, new table: %p",
 336         TableHeader->Signature,
 337         ACPI_CAST_PTR (void, TableDesc->Address),
 338         OverrideType, NewTable));
 339 
 340     /* We can now unmap/delete the original table (if fully mapped) */
 341 
 342     AcpiTbDeleteTable (TableDesc);
 343 
 344     /* Setup descriptor for the new table */
 345 
 346     TableDesc->Address = NewAddress;
 347     TableDesc->Pointer = NewTable;
 348     TableDesc->Length = NewTableLength;
 349     TableDesc->Flags = NewFlags;
 350 
 351     return (NewTable);
 352 }
 353 
 354 
 355 /*******************************************************************************
 356  *
 357  * FUNCTION:    AcpiTbResizeRootTableList
 358  *
 359  * PARAMETERS:  None
 360  *
 361  * RETURN:      Status
 362  *
 363  * DESCRIPTION: Expand the size of global table array
 364  *
 365  ******************************************************************************/
 366 
 367 ACPI_STATUS
 368 AcpiTbResizeRootTableList (
 369     void)
 370 {
 371     ACPI_TABLE_DESC         *Tables;
 372     UINT32                  TableCount;
 373 
 374 
 375     ACPI_FUNCTION_TRACE (TbResizeRootTableList);
 376 
 377 
 378     /* AllowResize flag is a parameter to AcpiInitializeTables */
 379 
 380     if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
 381     {
 382         ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
 383         return_ACPI_STATUS (AE_SUPPORT);
 384     }
 385 
 386     /* Increase the Table Array size */
 387 
 388     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 389     {
 390         TableCount = AcpiGbl_RootTableList.MaxTableCount;
 391     }
 392     else
 393     {
 394         TableCount = AcpiGbl_RootTableList.CurrentTableCount;
 395     }
 396 
 397     Tables = ACPI_ALLOCATE_ZEROED (
 398         ((ACPI_SIZE) TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT) *
 399         sizeof (ACPI_TABLE_DESC));
 400     if (!Tables)
 401     {
 402         ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
 403         return_ACPI_STATUS (AE_NO_MEMORY);
 404     }
 405 
 406     /* Copy and free the previous table array */
 407 
 408     if (AcpiGbl_RootTableList.Tables)
 409     {
 410         ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
 411             (ACPI_SIZE) TableCount * sizeof (ACPI_TABLE_DESC));
 412 
 413         if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 414         {
 415             ACPI_FREE (AcpiGbl_RootTableList.Tables);
 416         }
 417     }
 418 
 419     AcpiGbl_RootTableList.Tables = Tables;
 420     AcpiGbl_RootTableList.MaxTableCount =
 421         TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT;
 422     AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
 423 
 424     return_ACPI_STATUS (AE_OK);
 425 }
 426 
 427 
 428 /*******************************************************************************
 429  *
 430  * FUNCTION:    AcpiTbStoreTable
 431  *
 432  * PARAMETERS:  Address             - Table address
 433  *              Table               - Table header
 434  *              Length              - Table length
 435  *              Flags               - flags
 436  *
 437  * RETURN:      Status and table index.
 438  *
 439  * DESCRIPTION: Add an ACPI table to the global table list
 440  *
 441  ******************************************************************************/
 442 
 443 ACPI_STATUS
 444 AcpiTbStoreTable (
 445     ACPI_PHYSICAL_ADDRESS   Address,
 446     ACPI_TABLE_HEADER       *Table,
 447     UINT32                  Length,
 448     UINT8                   Flags,
 449     UINT32                  *TableIndex)
 450 {
 451     ACPI_STATUS             Status;
 452     ACPI_TABLE_DESC         *NewTable;
 453 
 454 
 455     /* Ensure that there is room for the table in the Root Table List */
 456 
 457     if (AcpiGbl_RootTableList.CurrentTableCount >=
 458         AcpiGbl_RootTableList.MaxTableCount)
 459     {
 460         Status = AcpiTbResizeRootTableList();
 461         if (ACPI_FAILURE (Status))
 462         {
 463             return (Status);
 464         }
 465     }
 466 
 467     NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
 468 
 469     /* Initialize added table */
 470 
 471     NewTable->Address = Address;
 472     NewTable->Pointer = Table;
 473     NewTable->Length = Length;
 474     NewTable->OwnerId = 0;
 475     NewTable->Flags = Flags;
 476 
 477     ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
 478 
 479     *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
 480     AcpiGbl_RootTableList.CurrentTableCount++;
 481     return (AE_OK);
 482 }
 483 
 484 
 485 /*******************************************************************************
 486  *
 487  * FUNCTION:    AcpiTbDeleteTable
 488  *
 489  * PARAMETERS:  TableIndex          - Table index
 490  *
 491  * RETURN:      None
 492  *
 493  * DESCRIPTION: Delete one internal ACPI table
 494  *
 495  ******************************************************************************/
 496 
 497 void
 498 AcpiTbDeleteTable (
 499     ACPI_TABLE_DESC         *TableDesc)
 500 {
 501 
 502     /* Table must be mapped or allocated */
 503 
 504     if (!TableDesc->Pointer)
 505     {
 506         return;
 507     }
 508 
 509     switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
 510     {
 511     case ACPI_TABLE_ORIGIN_MAPPED:
 512 
 513         AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
 514         break;
 515 
 516     case ACPI_TABLE_ORIGIN_ALLOCATED:
 517 
 518         ACPI_FREE (TableDesc->Pointer);
 519         break;
 520 
 521     /* Not mapped or allocated, there is nothing we can do */
 522 
 523     default:
 524 
 525         return;
 526     }
 527 
 528     TableDesc->Pointer = NULL;
 529 }
 530 
 531 
 532 /*******************************************************************************
 533  *
 534  * FUNCTION:    AcpiTbTerminate
 535  *
 536  * PARAMETERS:  None
 537  *
 538  * RETURN:      None
 539  *
 540  * DESCRIPTION: Delete all internal ACPI tables
 541  *
 542  ******************************************************************************/
 543 
 544 void
 545 AcpiTbTerminate (
 546     void)
 547 {
 548     UINT32                  i;
 549 
 550 
 551     ACPI_FUNCTION_TRACE (TbTerminate);
 552 
 553 
 554     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 555 
 556     /* Delete the individual tables */
 557 
 558     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
 559     {
 560         AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
 561     }
 562 
 563     /*
 564      * Delete the root table array if allocated locally. Array cannot be
 565      * mapped, so we don't need to check for that flag.
 566      */
 567     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 568     {
 569         ACPI_FREE (AcpiGbl_RootTableList.Tables);
 570     }
 571 
 572     AcpiGbl_RootTableList.Tables = NULL;
 573     AcpiGbl_RootTableList.Flags = 0;
 574     AcpiGbl_RootTableList.CurrentTableCount = 0;
 575 
 576     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
 577     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 578 
 579     return_VOID;
 580 }
 581 
 582 
 583 /*******************************************************************************
 584  *
 585  * FUNCTION:    AcpiTbDeleteNamespaceByOwner
 586  *
 587  * PARAMETERS:  TableIndex          - Table index
 588  *
 589  * RETURN:      Status
 590  *
 591  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
 592  *
 593  ******************************************************************************/
 594 
 595 ACPI_STATUS
 596 AcpiTbDeleteNamespaceByOwner (
 597     UINT32                  TableIndex)
 598 {
 599     ACPI_OWNER_ID           OwnerId;
 600     ACPI_STATUS             Status;
 601 
 602 
 603     ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
 604 
 605 
 606     Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 607     if (ACPI_FAILURE (Status))
 608     {
 609         return_ACPI_STATUS (Status);
 610     }
 611 
 612     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
 613     {
 614         /* The table index does not exist */
 615 
 616         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 617         return_ACPI_STATUS (AE_NOT_EXIST);
 618     }
 619 
 620     /* Get the owner ID for this table, used to delete namespace nodes */
 621 
 622     OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
 623     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 624 
 625     /*
 626      * Need to acquire the namespace writer lock to prevent interference
 627      * with any concurrent namespace walks. The interpreter must be
 628      * released during the deletion since the acquisition of the deletion
 629      * lock may block, and also since the execution of a namespace walk
 630      * must be allowed to use the interpreter.
 631      */
 632     (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
 633     Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
 634 
 635     AcpiNsDeleteNamespaceByOwner (OwnerId);
 636     if (ACPI_FAILURE (Status))
 637     {
 638         return_ACPI_STATUS (Status);
 639     }
 640 
 641     AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
 642 
 643     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
 644     return_ACPI_STATUS (Status);
 645 }
 646 
 647 
 648 /*******************************************************************************
 649  *
 650  * FUNCTION:    AcpiTbAllocateOwnerId
 651  *
 652  * PARAMETERS:  TableIndex          - Table index
 653  *
 654  * RETURN:      Status
 655  *
 656  * DESCRIPTION: Allocates OwnerId in TableDesc
 657  *
 658  ******************************************************************************/
 659 
 660 ACPI_STATUS
 661 AcpiTbAllocateOwnerId (
 662     UINT32                  TableIndex)
 663 {
 664     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 665 
 666 
 667     ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
 668 
 669 
 670     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 671     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 672     {
 673         Status = AcpiUtAllocateOwnerId
 674                     (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
 675     }
 676 
 677     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 678     return_ACPI_STATUS (Status);
 679 }
 680 
 681 
 682 /*******************************************************************************
 683  *
 684  * FUNCTION:    AcpiTbReleaseOwnerId
 685  *
 686  * PARAMETERS:  TableIndex          - Table index
 687  *
 688  * RETURN:      Status
 689  *
 690  * DESCRIPTION: Releases OwnerId in TableDesc
 691  *
 692  ******************************************************************************/
 693 
 694 ACPI_STATUS
 695 AcpiTbReleaseOwnerId (
 696     UINT32                  TableIndex)
 697 {
 698     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 699 
 700 
 701     ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
 702 
 703 
 704     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 705     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 706     {
 707         AcpiUtReleaseOwnerId (
 708             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
 709         Status = AE_OK;
 710     }
 711 
 712     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 713     return_ACPI_STATUS (Status);
 714 }
 715 
 716 
 717 /*******************************************************************************
 718  *
 719  * FUNCTION:    AcpiTbGetOwnerId
 720  *
 721  * PARAMETERS:  TableIndex          - Table index
 722  *              OwnerId             - Where the table OwnerId is returned
 723  *
 724  * RETURN:      Status
 725  *
 726  * DESCRIPTION: returns OwnerId for the ACPI table
 727  *
 728  ******************************************************************************/
 729 
 730 ACPI_STATUS
 731 AcpiTbGetOwnerId (
 732     UINT32                  TableIndex,
 733     ACPI_OWNER_ID           *OwnerId)
 734 {
 735     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 736 
 737 
 738     ACPI_FUNCTION_TRACE (TbGetOwnerId);
 739 
 740 
 741     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 742     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 743     {
 744         *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
 745         Status = AE_OK;
 746     }
 747 
 748     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 749     return_ACPI_STATUS (Status);
 750 }
 751 
 752 
 753 /*******************************************************************************
 754  *
 755  * FUNCTION:    AcpiTbIsTableLoaded
 756  *
 757  * PARAMETERS:  TableIndex          - Table index
 758  *
 759  * RETURN:      Table Loaded Flag
 760  *
 761  ******************************************************************************/
 762 
 763 BOOLEAN
 764 AcpiTbIsTableLoaded (
 765     UINT32                  TableIndex)
 766 {
 767     BOOLEAN                 IsLoaded = FALSE;
 768 
 769 
 770     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 771     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 772     {
 773         IsLoaded = (BOOLEAN)
 774             (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
 775             ACPI_TABLE_IS_LOADED);
 776     }
 777 
 778     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 779     return (IsLoaded);
 780 }
 781 
 782 
 783 /*******************************************************************************
 784  *
 785  * FUNCTION:    AcpiTbSetTableLoadedFlag
 786  *
 787  * PARAMETERS:  TableIndex          - Table index
 788  *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
 789  *
 790  * RETURN:      None
 791  *
 792  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
 793  *
 794  ******************************************************************************/
 795 
 796 void
 797 AcpiTbSetTableLoadedFlag (
 798     UINT32                  TableIndex,
 799     BOOLEAN                 IsLoaded)
 800 {
 801 
 802     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 803     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 804     {
 805         if (IsLoaded)
 806         {
 807             AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
 808                 ACPI_TABLE_IS_LOADED;
 809         }
 810         else
 811         {
 812             AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
 813                 ~ACPI_TABLE_IS_LOADED;
 814         }
 815     }
 816 
 817     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 818 }