Home | History | Annotate | Line # | Download | only in tables
tbxface.c revision 1.3
      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     ACPI_CONST_STRING       Signature,
    268     UINT32                  Instance,
    269     ACPI_TABLE_HEADER       *OutTableHeader)
    270 {
    271     UINT32                  i;
    272     UINT32                  j;
    273     ACPI_TABLE_HEADER       *Header;
    274     ACPI_STRING             USignature = __UNCONST(Signature);
    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                     USignature))
    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     ACPI_CONST_STRING       Signature,
    353     UINT32                  Instance,
    354     ACPI_TABLE_HEADER       **OutTable)
    355 {
    356     UINT32                  i;
    357     UINT32                  j;
    358     ACPI_STATUS             Status;
    359     ACPI_STRING             USignature = __UNCONST(Signature);
    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                 USignature))
    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