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