1 /******************************************************************************
   2  *
   3  * Module Name: tbinstal - ACPI table installation and removal
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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     /* FACS is the odd table, has no standard ACPI header and no checksum */
  97 
  98     if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
  99     {
 100         /* Always calculate checksum, ignore bad checksum if requested */
 101 
 102         Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
 103     }
 104 
 105     return_ACPI_STATUS (Status);
 106 }
 107 
 108 
 109 /*******************************************************************************
 110  *
 111  * FUNCTION:    AcpiTbAddTable
 112  *
 113  * PARAMETERS:  TableDesc           - Table descriptor
 114  *              TableIndex          - Where the table index is returned
 115  *
 116  * RETURN:      Status
 117  *
 118  * DESCRIPTION: This function is called to add an ACPI table. It is used to
 119  *              dynamically load tables via the Load and LoadTable AML
 120  *              operators.
 121  *
 122  ******************************************************************************/
 123 
 124 ACPI_STATUS
 125 AcpiTbAddTable (
 126     ACPI_TABLE_DESC         *TableDesc,
 127     UINT32                  *TableIndex)
 128 {
 129     UINT32                  i;
 130     ACPI_STATUS             Status = AE_OK;
 131     ACPI_TABLE_HEADER       *OverrideTable = NULL;
 132 
 133 
 134     ACPI_FUNCTION_TRACE (TbAddTable);
 135 
 136 
 137     if (!TableDesc->Pointer)
 138     {
 139         Status = AcpiTbVerifyTable (TableDesc);
 140         if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
 141         {
 142             return_ACPI_STATUS (Status);
 143         }
 144     }
 145 
 146     /*
 147      * Validate the incoming table signature.
 148      *
 149      * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
 150      * 2) We added support for OEMx tables, signature "OEM".
 151      * 3) Valid tables were encountered with a null signature, so we just
 152      *    gave up on validating the signature, (05/2008).
 153      * 4) We encountered non-AML tables such as the MADT, which caused
 154      *    interpreter errors and kernel faults. So now, we once again allow
 155      *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
 156      */
 157     if ((TableDesc->Pointer->Signature[0] != 0x00) &&
 158        (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
 159        (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
 160     {
 161         ACPI_ERROR ((AE_INFO,
 162             "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
 163             AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
 164                 TableDesc->Pointer->Signature : "????",
 165             *(UINT32 *) TableDesc->Pointer->Signature));
 166 
 167         return_ACPI_STATUS (AE_BAD_SIGNATURE);
 168     }
 169 
 170     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 171 
 172     /* Check if table is already registered */
 173 
 174     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
 175     {
 176         if (!AcpiGbl_RootTableList.Tables[i].Pointer)
 177         {
 178             Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
 179             if (ACPI_FAILURE (Status) ||
 180                 !AcpiGbl_RootTableList.Tables[i].Pointer)
 181             {
 182                 continue;
 183             }
 184         }
 185 
 186         /*
 187          * Check for a table match on the entire table length,
 188          * not just the header.
 189          */
 190         if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
 191         {
 192             continue;
 193         }
 194 
 195         if (ACPI_MEMCMP (TableDesc->Pointer,
 196                 AcpiGbl_RootTableList.Tables[i].Pointer,
 197                 AcpiGbl_RootTableList.Tables[i].Length))
 198         {
 199             continue;
 200         }
 201 
 202         /*
 203          * Note: the current mechanism does not unregister a table if it is
 204          * dynamically unloaded. The related namespace entries are deleted,
 205          * but the table remains in the root table list.
 206          *
 207          * The assumption here is that the number of different tables that
 208          * will be loaded is actually small, and there is minimal overhead
 209          * in just keeping the table in case it is needed again.
 210          *
 211          * If this assumption changes in the future (perhaps on large
 212          * machines with many table load/unload operations), tables will
 213          * need to be unregistered when they are unloaded, and slots in the
 214          * root table list should be reused when empty.
 215          */
 216 
 217         /*
 218          * Table is already registered.
 219          * We can delete the table that was passed as a parameter.
 220          */
 221         AcpiTbDeleteTable (TableDesc);
 222         *TableIndex = i;
 223 
 224         if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
 225         {
 226             /* Table is still loaded, this is an error */
 227 
 228             Status = AE_ALREADY_EXISTS;
 229             goto Release;
 230         }
 231         else
 232         {
 233             /* Table was unloaded, allow it to be reloaded */
 234 
 235             TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
 236             TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
 237             Status = AE_OK;
 238             goto PrintHeader;
 239         }
 240     }
 241 
 242     /*
 243      * ACPI Table Override:
 244      * Allow the host to override dynamically loaded tables.
 245      */
 246     Status = AcpiOsTableOverride (TableDesc->Pointer, &OverrideTable);
 247     if (ACPI_SUCCESS (Status) && OverrideTable)
 248     {
 249         ACPI_INFO ((AE_INFO,
 250             "%4.4s @ 0x%p Table override, replaced with:",
 251             TableDesc->Pointer->Signature,
 252             ACPI_CAST_PTR (void, TableDesc->Address)));
 253 
 254         /* We can delete the table that was passed as a parameter */
 255 
 256         AcpiTbDeleteTable (TableDesc);
 257 
 258         /* Setup descriptor for the new table */
 259 
 260         TableDesc->Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
 261         TableDesc->Pointer = OverrideTable;
 262         TableDesc->Length = OverrideTable->Length;
 263         TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
 264     }
 265 
 266     /* Add the table to the global root table list */
 267 
 268     Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
 269                 TableDesc->Length, TableDesc->Flags, TableIndex);
 270     if (ACPI_FAILURE (Status))
 271     {
 272         goto Release;
 273     }
 274 
 275 PrintHeader:
 276     AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
 277 
 278 Release:
 279     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 280     return_ACPI_STATUS (Status);
 281 }
 282 
 283 
 284 /*******************************************************************************
 285  *
 286  * FUNCTION:    AcpiTbResizeRootTableList
 287  *
 288  * PARAMETERS:  None
 289  *
 290  * RETURN:      Status
 291  *
 292  * DESCRIPTION: Expand the size of global table array
 293  *
 294  ******************************************************************************/
 295 
 296 ACPI_STATUS
 297 AcpiTbResizeRootTableList (
 298     void)
 299 {
 300     ACPI_TABLE_DESC         *Tables;
 301 
 302 
 303     ACPI_FUNCTION_TRACE (TbResizeRootTableList);
 304 
 305 
 306     /* AllowResize flag is a parameter to AcpiInitializeTables */
 307 
 308     if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
 309     {
 310         ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
 311         return_ACPI_STATUS (AE_SUPPORT);
 312     }
 313 
 314     /* Increase the Table Array size */
 315 
 316     Tables = ACPI_ALLOCATE_ZEROED (
 317         ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
 318             ACPI_ROOT_TABLE_SIZE_INCREMENT) *
 319         sizeof (ACPI_TABLE_DESC));
 320     if (!Tables)
 321     {
 322         ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
 323         return_ACPI_STATUS (AE_NO_MEMORY);
 324     }
 325 
 326     /* Copy and free the previous table array */
 327 
 328     if (AcpiGbl_RootTableList.Tables)
 329     {
 330         ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
 331             (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
 332 
 333         if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 334         {
 335             ACPI_FREE (AcpiGbl_RootTableList.Tables);
 336         }
 337     }
 338 
 339     AcpiGbl_RootTableList.Tables = Tables;
 340     AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
 341     AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
 342 
 343     return_ACPI_STATUS (AE_OK);
 344 }
 345 
 346 
 347 /*******************************************************************************
 348  *
 349  * FUNCTION:    AcpiTbStoreTable
 350  *
 351  * PARAMETERS:  Address             - Table address
 352  *              Table               - Table header
 353  *              Length              - Table length
 354  *              Flags               - flags
 355  *
 356  * RETURN:      Status and table index.
 357  *
 358  * DESCRIPTION: Add an ACPI table to the global table list
 359  *
 360  ******************************************************************************/
 361 
 362 ACPI_STATUS
 363 AcpiTbStoreTable (
 364     ACPI_PHYSICAL_ADDRESS   Address,
 365     ACPI_TABLE_HEADER       *Table,
 366     UINT32                  Length,
 367     UINT8                   Flags,
 368     UINT32                  *TableIndex)
 369 {
 370     ACPI_STATUS             Status;
 371     ACPI_TABLE_DESC         *NewTable;
 372 
 373 
 374     /* Ensure that there is room for the table in the Root Table List */
 375 
 376     if (AcpiGbl_RootTableList.CurrentTableCount >=
 377         AcpiGbl_RootTableList.MaxTableCount)
 378     {
 379         Status = AcpiTbResizeRootTableList();
 380         if (ACPI_FAILURE (Status))
 381         {
 382             return (Status);
 383         }
 384     }
 385 
 386     NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
 387 
 388     /* Initialize added table */
 389 
 390     NewTable->Address = Address;
 391     NewTable->Pointer = Table;
 392     NewTable->Length = Length;
 393     NewTable->OwnerId = 0;
 394     NewTable->Flags = Flags;
 395 
 396     ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
 397 
 398     *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
 399     AcpiGbl_RootTableList.CurrentTableCount++;
 400     return (AE_OK);
 401 }
 402 
 403 
 404 /*******************************************************************************
 405  *
 406  * FUNCTION:    AcpiTbDeleteTable
 407  *
 408  * PARAMETERS:  TableIndex          - Table index
 409  *
 410  * RETURN:      None
 411  *
 412  * DESCRIPTION: Delete one internal ACPI table
 413  *
 414  ******************************************************************************/
 415 
 416 void
 417 AcpiTbDeleteTable (
 418     ACPI_TABLE_DESC         *TableDesc)
 419 {
 420 
 421     /* Table must be mapped or allocated */
 422 
 423     if (!TableDesc->Pointer)
 424     {
 425         return;
 426     }
 427 
 428     switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
 429     {
 430     case ACPI_TABLE_ORIGIN_MAPPED:
 431         AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
 432         break;
 433 
 434     case ACPI_TABLE_ORIGIN_ALLOCATED:
 435         ACPI_FREE (TableDesc->Pointer);
 436         break;
 437 
 438     default:
 439         break;
 440     }
 441 
 442     TableDesc->Pointer = NULL;
 443 }
 444 
 445 
 446 /*******************************************************************************
 447  *
 448  * FUNCTION:    AcpiTbTerminate
 449  *
 450  * PARAMETERS:  None
 451  *
 452  * RETURN:      None
 453  *
 454  * DESCRIPTION: Delete all internal ACPI tables
 455  *
 456  ******************************************************************************/
 457 
 458 void
 459 AcpiTbTerminate (
 460     void)
 461 {
 462     UINT32                  i;
 463 
 464 
 465     ACPI_FUNCTION_TRACE (TbTerminate);
 466 
 467 
 468     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 469 
 470     /* Delete the individual tables */
 471 
 472     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
 473     {
 474         AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
 475     }
 476 
 477     /*
 478      * Delete the root table array if allocated locally. Array cannot be
 479      * mapped, so we don't need to check for that flag.
 480      */
 481     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 482     {
 483         ACPI_FREE (AcpiGbl_RootTableList.Tables);
 484     }
 485 
 486     AcpiGbl_RootTableList.Tables = NULL;
 487     AcpiGbl_RootTableList.Flags = 0;
 488     AcpiGbl_RootTableList.CurrentTableCount = 0;
 489 
 490     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
 491     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 492 }
 493 
 494 
 495 /*******************************************************************************
 496  *
 497  * FUNCTION:    AcpiTbDeleteNamespaceByOwner
 498  *
 499  * PARAMETERS:  TableIndex          - Table index
 500  *
 501  * RETURN:      Status
 502  *
 503  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
 504  *
 505  ******************************************************************************/
 506 
 507 ACPI_STATUS
 508 AcpiTbDeleteNamespaceByOwner (
 509     UINT32                  TableIndex)
 510 {
 511     ACPI_OWNER_ID           OwnerId;
 512     ACPI_STATUS             Status;
 513 
 514 
 515     ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
 516 
 517 
 518     Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 519     if (ACPI_FAILURE (Status))
 520     {
 521         return_ACPI_STATUS (Status);
 522     }
 523 
 524     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
 525     {
 526         /* The table index does not exist */
 527 
 528         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 529         return_ACPI_STATUS (AE_NOT_EXIST);
 530     }
 531 
 532     /* Get the owner ID for this table, used to delete namespace nodes */
 533 
 534     OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
 535     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 536 
 537     /*
 538      * Need to acquire the namespace writer lock to prevent interference
 539      * with any concurrent namespace walks. The interpreter must be
 540      * released during the deletion since the acquisition of the deletion
 541      * lock may block, and also since the execution of a namespace walk
 542      * must be allowed to use the interpreter.
 543      */
 544     (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
 545     Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
 546 
 547     AcpiNsDeleteNamespaceByOwner (OwnerId);
 548     if (ACPI_FAILURE (Status))
 549     {
 550         return_ACPI_STATUS (Status);
 551     }
 552 
 553     AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
 554 
 555     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
 556     return_ACPI_STATUS (Status);
 557 }
 558 
 559 
 560 /*******************************************************************************
 561  *
 562  * FUNCTION:    AcpiTbAllocateOwnerId
 563  *
 564  * PARAMETERS:  TableIndex          - Table index
 565  *
 566  * RETURN:      Status
 567  *
 568  * DESCRIPTION: Allocates OwnerId in TableDesc
 569  *
 570  ******************************************************************************/
 571 
 572 ACPI_STATUS
 573 AcpiTbAllocateOwnerId (
 574     UINT32                  TableIndex)
 575 {
 576     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 577 
 578 
 579     ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
 580 
 581 
 582     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 583     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 584     {
 585         Status = AcpiUtAllocateOwnerId
 586                     (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
 587     }
 588 
 589     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 590     return_ACPI_STATUS (Status);
 591 }
 592 
 593 
 594 /*******************************************************************************
 595  *
 596  * FUNCTION:    AcpiTbReleaseOwnerId
 597  *
 598  * PARAMETERS:  TableIndex          - Table index
 599  *
 600  * RETURN:      Status
 601  *
 602  * DESCRIPTION: Releases OwnerId in TableDesc
 603  *
 604  ******************************************************************************/
 605 
 606 ACPI_STATUS
 607 AcpiTbReleaseOwnerId (
 608     UINT32                  TableIndex)
 609 {
 610     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 611 
 612 
 613     ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
 614 
 615 
 616     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 617     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 618     {
 619         AcpiUtReleaseOwnerId (
 620             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
 621         Status = AE_OK;
 622     }
 623 
 624     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 625     return_ACPI_STATUS (Status);
 626 }
 627 
 628 
 629 /*******************************************************************************
 630  *
 631  * FUNCTION:    AcpiTbGetOwnerId
 632  *
 633  * PARAMETERS:  TableIndex          - Table index
 634  *              OwnerId             - Where the table OwnerId is returned
 635  *
 636  * RETURN:      Status
 637  *
 638  * DESCRIPTION: returns OwnerId for the ACPI table
 639  *
 640  ******************************************************************************/
 641 
 642 ACPI_STATUS
 643 AcpiTbGetOwnerId (
 644     UINT32                  TableIndex,
 645     ACPI_OWNER_ID           *OwnerId)
 646 {
 647     ACPI_STATUS             Status = AE_BAD_PARAMETER;
 648 
 649 
 650     ACPI_FUNCTION_TRACE (TbGetOwnerId);
 651 
 652 
 653     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 654     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 655     {
 656         *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
 657         Status = AE_OK;
 658     }
 659 
 660     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 661     return_ACPI_STATUS (Status);
 662 }
 663 
 664 
 665 /*******************************************************************************
 666  *
 667  * FUNCTION:    AcpiTbIsTableLoaded
 668  *
 669  * PARAMETERS:  TableIndex          - Table index
 670  *
 671  * RETURN:      Table Loaded Flag
 672  *
 673  ******************************************************************************/
 674 
 675 BOOLEAN
 676 AcpiTbIsTableLoaded (
 677     UINT32                  TableIndex)
 678 {
 679     BOOLEAN                 IsLoaded = FALSE;
 680 
 681 
 682     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 683     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 684     {
 685         IsLoaded = (BOOLEAN)
 686             (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
 687             ACPI_TABLE_IS_LOADED);
 688     }
 689 
 690     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 691     return (IsLoaded);
 692 }
 693 
 694 
 695 /*******************************************************************************
 696  *
 697  * FUNCTION:    AcpiTbSetTableLoadedFlag
 698  *
 699  * PARAMETERS:  TableIndex          - Table index
 700  *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
 701  *
 702  * RETURN:      None
 703  *
 704  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
 705  *
 706  ******************************************************************************/
 707 
 708 void
 709 AcpiTbSetTableLoadedFlag (
 710     UINT32                  TableIndex,
 711     BOOLEAN                 IsLoaded)
 712 {
 713 
 714     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 715     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
 716     {
 717         if (IsLoaded)
 718         {
 719             AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
 720                 ACPI_TABLE_IS_LOADED;
 721         }
 722         else
 723         {
 724             AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
 725                 ~ACPI_TABLE_IS_LOADED;
 726         }
 727     }
 728 
 729     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 730 }
 731