Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/exconfig.c need to be fixed.

0001 /******************************************************************************
0002  *
0003  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights.  You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code.  No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision.  In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change.  Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee.  Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution.  In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0086 
0087  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0088  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0089  * PARTICULAR PURPOSE.
0090  *
0091  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0092  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0093  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0094  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0095  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0096  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0097  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0098  * LIMITED REMEDY.
0099  *
0100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0101  * software or system incorporating such software without first obtaining any
0102  * required license or other approval from the U. S. Department of Commerce or
0103  * any other agency or department of the United States Government.  In the
0104  * event Licensee exports any such software from the United States or
0105  * re-exports any such software from a foreign destination, Licensee shall
0106  * ensure that the distribution and export/re-export of the software is in
0107  * compliance with all laws, regulations, orders, or other restrictions of the
0108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0109  * any of its subsidiaries will export/re-export any technical data, process,
0110  * software, or service, directly or indirectly, to any country for which the
0111  * United States government or any agency thereof requires an export license,
0112  * other governmental approval, or letter of assurance, without first obtaining
0113  * such license, approval or letter.
0114  *
0115  *****************************************************************************/
0116 
0117 #define __EXCONFIG_C__
0118 
0119 #include "acpi.h"
0120 #include "accommon.h"
0121 #include "acinterp.h"
0122 #include "acnamesp.h"
0123 #include "actables.h"
0124 #include "acdispat.h"
0125 #include "acevents.h"
0126 
0127 
0128 #define _COMPONENT          ACPI_EXECUTER
0129         ACPI_MODULE_NAME    ("exconfig")
0130 
0131 /* Local prototypes */
0132 
0133 static ACPI_STATUS
0134 AcpiExAddTable (
0135     UINT32                  TableIndex,
0136     ACPI_NAMESPACE_NODE     *ParentNode,
0137     ACPI_OPERAND_OBJECT     **DdbHandle);
0138 
0139 static ACPI_STATUS
0140 AcpiExRegionRead (
0141     ACPI_OPERAND_OBJECT     *ObjDesc,
0142     UINT32                  Length,
0143     UINT8                   *Buffer);
0144 
0145 
0146 /*******************************************************************************
0147  *
0148  * FUNCTION:    AcpiExAddTable
0149  *
0150  * PARAMETERS:  Table               - Pointer to raw table
0151  *              ParentNode          - Where to load the table (scope)
0152  *              DdbHandle           - Where to return the table handle.
0153  *
0154  * RETURN:      Status
0155  *
0156  * DESCRIPTION: Common function to Install and Load an ACPI table with a
0157  *              returned table handle.
0158  *
0159  ******************************************************************************/
0160 
0161 static ACPI_STATUS
0162 AcpiExAddTable (
0163     UINT32                  TableIndex,
0164     ACPI_NAMESPACE_NODE     *ParentNode,
0165     ACPI_OPERAND_OBJECT     **DdbHandle)
0166 {
0167     ACPI_STATUS             Status;
0168     ACPI_OPERAND_OBJECT     *ObjDesc;
0169 
0170 
0171     ACPI_FUNCTION_TRACE (ExAddTable);
0172 
0173 
0174     /* Create an object to be the table handle */
0175 
0176     ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
0177     if (!ObjDesc)
0178     {
0179         return_ACPI_STATUS (AE_NO_MEMORY);
0180     }
0181 
0182     /* Init the table handle */
0183 
0184     ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
0185     ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE;
0186     *DdbHandle = ObjDesc;
0187 
0188     /* Install the new table into the local data structures */
0189 
0190     ObjDesc->Reference.Value = TableIndex;
0191 
0192     /* Add the table to the namespace */
0193 
0194     Status = AcpiNsLoadTable (TableIndex, ParentNode);
0195     if (ACPI_FAILURE (Status))
0196     {
0197         AcpiUtRemoveReference (ObjDesc);
0198         *DdbHandle = NULL;
0199     }
0200 
0201     return_ACPI_STATUS (Status);
0202 }
0203 
0204 
0205 /*******************************************************************************
0206  *
0207  * FUNCTION:    AcpiExLoadTableOp
0208  *
0209  * PARAMETERS:  WalkState           - Current state with operands
0210  *              ReturnDesc          - Where to store the return object
0211  *
0212  * RETURN:      Status
0213  *
0214  * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
0215  *
0216  ******************************************************************************/
0217 
0218 ACPI_STATUS
0219 AcpiExLoadTableOp (
0220     ACPI_WALK_STATE         *WalkState,
0221     ACPI_OPERAND_OBJECT     **ReturnDesc)
0222 {
0223     ACPI_STATUS             Status;
0224     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
0225     ACPI_NAMESPACE_NODE     *ParentNode;
0226     ACPI_NAMESPACE_NODE     *StartNode;
0227     ACPI_NAMESPACE_NODE     *ParameterNode = NULL;
0228     ACPI_OPERAND_OBJECT     *DdbHandle;
0229     ACPI_TABLE_HEADER       *Table;
0230     UINT32                  TableIndex;
0231 
0232 
0233     ACPI_FUNCTION_TRACE (ExLoadTableOp);
0234 
0235 
0236     /* Validate lengths for the SignatureString, OEMIDString, OEMTableID */
0237 
0238     if ((Operand[0]->String.Length > ACPI_NAME_SIZE) ||
0239         (Operand[1]->String.Length > ACPI_OEM_ID_SIZE) ||
0240         (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE))
0241     {
0242         return_ACPI_STATUS (AE_BAD_PARAMETER);
0243     }
0244 
0245     /* Find the ACPI table in the RSDT/XSDT */
0246 
0247     Status = AcpiTbFindTable (Operand[0]->String.Pointer,
0248                               Operand[1]->String.Pointer,
0249                               Operand[2]->String.Pointer, &TableIndex);
0250     if (ACPI_FAILURE (Status))
0251     {
0252         if (Status != AE_NOT_FOUND)
0253         {
0254             return_ACPI_STATUS (Status);
0255         }
0256 
0257         /* Table not found, return an Integer=0 and AE_OK */
0258 
0259         DdbHandle = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
0260         if (!DdbHandle)
0261         {
0262             return_ACPI_STATUS (AE_NO_MEMORY);
0263         }
0264 
0265         DdbHandle->Integer.Value = 0;
0266         *ReturnDesc = DdbHandle;
0267 
0268         return_ACPI_STATUS (AE_OK);
0269     }
0270 
0271     /* Default nodes */
0272 
0273     StartNode = WalkState->ScopeInfo->Scope.Node;
0274     ParentNode = AcpiGbl_RootNode;
0275 
0276     /* RootPath (optional parameter) */
0277 
0278     if (Operand[3]->String.Length > 0)
0279     {
0280         /*
0281          * Find the node referenced by the RootPathString.  This is the
0282          * location within the namespace where the table will be loaded.
0283          */
0284         Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer,
0285                     ACPI_NS_SEARCH_PARENT, &ParentNode);
0286         if (ACPI_FAILURE (Status))
0287         {
0288             return_ACPI_STATUS (Status);
0289         }
0290     }
0291 
0292     /* ParameterPath (optional parameter) */
0293 
0294     if (Operand[4]->String.Length > 0)
0295     {
0296         if ((Operand[4]->String.Pointer[0] != '\\') &&
0297             (Operand[4]->String.Pointer[0] != '^'))
0298         {
0299             /*
0300              * Path is not absolute, so it will be relative to the node
0301              * referenced by the RootPathString (or the NS root if omitted)
0302              */
0303             StartNode = ParentNode;
0304         }
0305 
0306         /* Find the node referenced by the ParameterPathString */
0307 
0308         Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer,
0309                     ACPI_NS_SEARCH_PARENT, &ParameterNode);
0310         if (ACPI_FAILURE (Status))
0311         {
0312             return_ACPI_STATUS (Status);
0313         }
0314     }
0315 
0316     /* Load the table into the namespace */
0317 
0318     Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle);
0319     if (ACPI_FAILURE (Status))
0320     {
0321         return_ACPI_STATUS (Status);
0322     }
0323 
0324     /* Parameter Data (optional) */
0325 
0326     if (ParameterNode)
0327     {
0328         /* Store the parameter data into the optional parameter object */
0329 
0330         Status = AcpiExStore (Operand[5],
0331                     ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode),
0332                     WalkState);
0333         if (ACPI_FAILURE (Status))
0334         {
0335             (void) AcpiExUnloadTable (DdbHandle);
0336 
0337             AcpiUtRemoveReference (DdbHandle);
0338             return_ACPI_STATUS (Status);
0339         }
0340     }
0341 
0342     Status = AcpiGetTableByIndex (TableIndex, &Table);
0343     if (ACPI_SUCCESS (Status))
0344     {
0345         ACPI_INFO ((AE_INFO,
0346             "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
0347             Table->Signature, Table->OemId, Table->OemTableId));
0348     }
0349 
0350     /* Invoke table handler if present */
0351 
0352     if (AcpiGbl_TableHandler)
0353     {
0354         (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
0355                     AcpiGbl_TableHandlerContext);
0356     }
0357 
0358     *ReturnDesc = DdbHandle;
0359     return_ACPI_STATUS  (Status);
0360 }
0361 
0362 
0363 /*******************************************************************************
0364  *
0365  * FUNCTION:    AcpiExRegionRead
0366  *
0367  * PARAMETERS:  ObjDesc         - Region descriptor
0368  *              Length          - Number of bytes to read
0369  *              Buffer          - Pointer to where to put the data
0370  *
0371  * RETURN:      Status
0372  *
0373  * DESCRIPTION: Read data from an operation region. The read starts from the
0374  *              beginning of the region.
0375  *
0376  ******************************************************************************/
0377 
0378 static ACPI_STATUS
0379 AcpiExRegionRead (
0380     ACPI_OPERAND_OBJECT     *ObjDesc,
0381     UINT32                  Length,
0382     UINT8                   *Buffer)
0383 {
0384     ACPI_STATUS             Status;
0385     ACPI_INTEGER            Value;
0386     UINT32                  RegionOffset = 0;
0387     UINT32                  i;
0388 
0389 
0390     /* Bytewise reads */
0391 
0392     for (i = 0; i < Length; i++)
0393     {
0394         Status = AcpiEvAddressSpaceDispatch (ObjDesc, ACPI_READ,
0395                     RegionOffset, 8, &Value);
0396         if (ACPI_FAILURE (Status))
0397         {
0398             return (Status);
0399         }
0400 
0401         *Buffer = (UINT8) Value;
0402         Buffer++;
0403         RegionOffset++;
0404     }
0405 
0406     return (AE_OK);
0407 }
0408 
0409 
0410 /*******************************************************************************
0411  *
0412  * FUNCTION:    AcpiExLoadOp
0413  *
0414  * PARAMETERS:  ObjDesc         - Region or Buffer/Field where the table will be
0415  *                                obtained
0416  *              Target          - Where a handle to the table will be stored
0417  *              WalkState       - Current state
0418  *
0419  * RETURN:      Status
0420  *
0421  * DESCRIPTION: Load an ACPI table from a field or operation region
0422  *
0423  * NOTE: Region Fields (Field, BankField, IndexFields) are resolved to buffer
0424  *       objects before this code is reached.
0425  *
0426  *       If source is an operation region, it must refer to SystemMemory, as
0427  *       per the ACPI specification.
0428  *
0429  ******************************************************************************/
0430 
0431 ACPI_STATUS
0432 AcpiExLoadOp (
0433     ACPI_OPERAND_OBJECT     *ObjDesc,
0434     ACPI_OPERAND_OBJECT     *Target,
0435     ACPI_WALK_STATE         *WalkState)
0436 {
0437     ACPI_OPERAND_OBJECT     *DdbHandle;
0438     ACPI_TABLE_HEADER       *Table;
0439     ACPI_TABLE_DESC         TableDesc;
0440     UINT32                  TableIndex;
0441     ACPI_STATUS             Status;
0442     UINT32                  Length;
0443 
0444 
0445     ACPI_FUNCTION_TRACE (ExLoadOp);
0446 
0447 
0448     ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC));
0449 
0450     /* Source Object can be either an OpRegion or a Buffer/Field */
0451 
0452     switch (ObjDesc->Common.Type)
0453     {
0454     case ACPI_TYPE_REGION:
0455 
0456         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
0457             "Load table from Region %p\n", ObjDesc));
0458 
0459         /* Region must be SystemMemory (from ACPI spec) */
0460 
0461         if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY)
0462         {
0463             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
0464         }
0465 
0466         /*
0467          * If the Region Address and Length have not been previously evaluated,
0468          * evaluate them now and save the results.
0469          */
0470         if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
0471         {
0472             Status = AcpiDsGetRegionArguments (ObjDesc);
0473             if (ACPI_FAILURE (Status))
0474             {
0475                 return_ACPI_STATUS (Status);
0476             }
0477         }
0478 
0479         /* Get the table header first so we can get the table length */
0480 
0481         Table = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER));
0482         if (!Table)
0483         {
0484             return_ACPI_STATUS (AE_NO_MEMORY);
0485         }
0486 
0487         Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER),
0488                     ACPI_CAST_PTR (UINT8, Table));
0489         Length = Table->Length;
0490         ACPI_FREE (Table);
0491 
0492         if (ACPI_FAILURE (Status))
0493         {
0494             return_ACPI_STATUS (Status);
0495         }
0496 
0497         /* Must have at least an ACPI table header */
0498 
0499         if (Length < sizeof (ACPI_TABLE_HEADER))
0500         {
0501             return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
0502         }
0503 
0504         /*
0505          * The original implementation simply mapped the table, with no copy.
0506          * However, the memory region is not guaranteed to remain stable and
0507          * we must copy the table to a local buffer. For example, the memory
0508          * region is corrupted after suspend on some machines. Dynamically
0509          * loaded tables are usually small, so this overhead is minimal.
0510          *
0511          * The latest implementation (5/2009) does not use a mapping at all.
0512          * We use the low-level operation region interface to read the table
0513          * instead of the obvious optimization of using a direct mapping.
0514          * This maintains a consistent use of operation regions across the
0515          * entire subsystem. This is important if additional processing must
0516          * be performed in the (possibly user-installed) operation region
0517          * handler. For example, AcpiExec and ASLTS depend on this.
0518          */
0519 
0520         /* Allocate a buffer for the table */
0521 
0522         TableDesc.Pointer = ACPI_ALLOCATE (Length);
0523         if (!TableDesc.Pointer)
0524         {
0525             return_ACPI_STATUS (AE_NO_MEMORY);
0526         }
0527 
0528         /* Read the entire table */
0529 
0530         Status = AcpiExRegionRead (ObjDesc, Length,
0531                     ACPI_CAST_PTR (UINT8, TableDesc.Pointer));
0532         if (ACPI_FAILURE (Status))
0533         {
0534             ACPI_FREE (TableDesc.Pointer);
0535             return_ACPI_STATUS (Status);
0536         }
0537 
0538         TableDesc.Address = ObjDesc->Region.Address;
0539         break;
0540 
0541 
0542     case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */
0543 
0544         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
0545             "Load table from Buffer or Field %p\n", ObjDesc));
0546 
0547         /* Must have at least an ACPI table header */
0548 
0549         if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER))
0550         {
0551             return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
0552         }
0553 
0554         /* Get the actual table length from the table header */
0555 
0556         Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer);
0557         Length = Table->Length;
0558 
0559         /* Table cannot extend beyond the buffer */
0560 
0561         if (Length > ObjDesc->Buffer.Length)
0562         {
0563             return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
0564         }
0565         if (Length < sizeof (ACPI_TABLE_HEADER))
0566         {
0567             return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
0568         }
0569 
0570         /*
0571          * Copy the table from the buffer because the buffer could be modified
0572          * or even deleted in the future
0573          */
0574         TableDesc.Pointer = ACPI_ALLOCATE (Length);
0575         if (!TableDesc.Pointer)
0576         {
0577             return_ACPI_STATUS (AE_NO_MEMORY);
0578         }
0579 
0580         ACPI_MEMCPY (TableDesc.Pointer, Table, Length);
0581         TableDesc.Address = ACPI_TO_INTEGER (TableDesc.Pointer);
0582         break;
0583 
0584 
0585     default:
0586         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
0587     }
0588 
0589     /* Validate table checksum (will not get validated in TbAddTable) */
0590 
0591     Status = AcpiTbVerifyChecksum (TableDesc.Pointer, Length);
0592     if (ACPI_FAILURE (Status))
0593     {
0594         ACPI_FREE (TableDesc.Pointer);
0595         return_ACPI_STATUS (Status);
0596     }
0597 
0598     /* Complete the table descriptor */
0599 
0600     TableDesc.Length = Length;
0601     TableDesc.Flags = ACPI_TABLE_ORIGIN_ALLOCATED;
0602 
0603     /* Install the new table into the local data structures */
0604 
0605     Status = AcpiTbAddTable (&TableDesc, &TableIndex);
0606     if (ACPI_FAILURE (Status))
0607     {
0608         goto Cleanup;
0609     }
0610 
0611     /*
0612      * Add the table to the namespace.
0613      *
0614      * Note: Load the table objects relative to the root of the namespace.
0615      * This appears to go against the ACPI specification, but we do it for
0616      * compatibility with other ACPI implementations.
0617      */
0618     Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle);
0619     if (ACPI_FAILURE (Status))
0620     {
0621         /* On error, TablePtr was deallocated above */
0622 
0623         return_ACPI_STATUS (Status);
0624     }
0625 
0626     /* Store the DdbHandle into the Target operand */
0627 
0628     Status = AcpiExStore (DdbHandle, Target, WalkState);
0629     if (ACPI_FAILURE (Status))
0630     {
0631         (void) AcpiExUnloadTable (DdbHandle);
0632 
0633         /* TablePtr was deallocated above */
0634 
0635         AcpiUtRemoveReference (DdbHandle);
0636         return_ACPI_STATUS (Status);
0637     }
0638 
0639     /* Remove the reference by added by AcpiExStore above */
0640 
0641     AcpiUtRemoveReference (DdbHandle);
0642 
0643     /* Invoke table handler if present */
0644 
0645     if (AcpiGbl_TableHandler)
0646     {
0647         (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, TableDesc.Pointer,
0648                     AcpiGbl_TableHandlerContext);
0649     }
0650 
0651 Cleanup:
0652     if (ACPI_FAILURE (Status))
0653     {
0654         /* Delete allocated table buffer */
0655 
0656         AcpiTbDeleteTable (&TableDesc);
0657     }
0658     return_ACPI_STATUS (Status);
0659 }
0660 
0661 
0662 /*******************************************************************************
0663  *
0664  * FUNCTION:    AcpiExUnloadTable
0665  *
0666  * PARAMETERS:  DdbHandle           - Handle to a previously loaded table
0667  *
0668  * RETURN:      Status
0669  *
0670  * DESCRIPTION: Unload an ACPI table
0671  *
0672  ******************************************************************************/
0673 
0674 ACPI_STATUS
0675 AcpiExUnloadTable (
0676     ACPI_OPERAND_OBJECT     *DdbHandle)
0677 {
0678     ACPI_STATUS             Status = AE_OK;
0679     ACPI_OPERAND_OBJECT     *TableDesc = DdbHandle;
0680     UINT32                  TableIndex;
0681     ACPI_TABLE_HEADER       *Table;
0682 
0683 
0684     ACPI_FUNCTION_TRACE (ExUnloadTable);
0685 
0686 
0687     /*
0688      * Validate the handle
0689      * Although the handle is partially validated in AcpiExReconfiguration()
0690      * when it calls AcpiExResolveOperands(), the handle is more completely
0691      * validated here.
0692      *
0693      * Handle must be a valid operand object of type reference. Also, the
0694      * DdbHandle must still be marked valid (table has not been previously
0695      * unloaded)
0696      */
0697     if ((!DdbHandle) ||
0698         (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) ||
0699         (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) ||
0700         (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID)))
0701     {
0702         return_ACPI_STATUS (AE_BAD_PARAMETER);
0703     }
0704 
0705     /* Get the table index from the DdbHandle */
0706 
0707     TableIndex = TableDesc->Reference.Value;
0708 
0709     /* Ensure the table is still loaded */
0710 
0711     if (!AcpiTbIsTableLoaded (TableIndex))
0712     {
0713         return_ACPI_STATUS (AE_NOT_EXIST);
0714     }
0715 
0716     /* Invoke table handler if present */
0717 
0718     if (AcpiGbl_TableHandler)
0719     {
0720         Status = AcpiGetTableByIndex (TableIndex, &Table);
0721         if (ACPI_SUCCESS (Status))
0722         {
0723             (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table,
0724                         AcpiGbl_TableHandlerContext);
0725         }
0726     }
0727 
0728     /* Delete the portion of the namespace owned by this table */
0729 
0730     Status = AcpiTbDeleteNamespaceByOwner (TableIndex);
0731     if (ACPI_FAILURE (Status))
0732     {
0733         return_ACPI_STATUS (Status);
0734     }
0735 
0736     (void) AcpiTbReleaseOwnerId (TableIndex);
0737     AcpiTbSetTableLoadedFlag (TableIndex, FALSE);
0738 
0739     /*
0740      * Invalidate the handle. We do this because the handle may be stored
0741      * in a named object and may not be actually deleted until much later.
0742      */
0743     DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID;
0744     return_ACPI_STATUS (AE_OK);
0745 }
0746