Home | History | Annotate | Line # | Download | only in namespace
nsxfeval.c revision 1.1.1.8
      1 /*******************************************************************************
      2  *
      3  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
      4  *                         ACPI Object evaluation interfaces
      5  *
      6  ******************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2016, 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 EXPORT_ACPI_INTERFACES
     46 
     47 #include "acpi.h"
     48 #include "accommon.h"
     49 #include "acnamesp.h"
     50 #include "acinterp.h"
     51 
     52 
     53 #define _COMPONENT          ACPI_NAMESPACE
     54         ACPI_MODULE_NAME    ("nsxfeval")
     55 
     56 /* Local prototypes */
     57 
     58 static void
     59 AcpiNsResolveReferences (
     60     ACPI_EVALUATE_INFO      *Info);
     61 
     62 
     63 /*******************************************************************************
     64  *
     65  * FUNCTION:    AcpiEvaluateObjectTyped
     66  *
     67  * PARAMETERS:  Handle              - Object handle (optional)
     68  *              Pathname            - Object pathname (optional)
     69  *              ExternalParams      - List of parameters to pass to method,
     70  *                                    terminated by NULL. May be NULL
     71  *                                    if no parameters are being passed.
     72  *              ReturnBuffer        - Where to put method's return value (if
     73  *                                    any). If NULL, no value is returned.
     74  *              ReturnType          - Expected type of return object
     75  *
     76  * RETURN:      Status
     77  *
     78  * DESCRIPTION: Find and evaluate the given object, passing the given
     79  *              parameters if necessary. One of "Handle" or "Pathname" must
     80  *              be valid (non-null)
     81  *
     82  ******************************************************************************/
     83 
     84 ACPI_STATUS
     85 AcpiEvaluateObjectTyped (
     86     ACPI_HANDLE             Handle,
     87     ACPI_STRING             Pathname,
     88     ACPI_OBJECT_LIST        *ExternalParams,
     89     ACPI_BUFFER             *ReturnBuffer,
     90     ACPI_OBJECT_TYPE        ReturnType)
     91 {
     92     ACPI_STATUS             Status;
     93     BOOLEAN                 FreeBufferOnError = FALSE;
     94 
     95 
     96     ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
     97 
     98 
     99     /* Return buffer must be valid */
    100 
    101     if (!ReturnBuffer)
    102     {
    103         return_ACPI_STATUS (AE_BAD_PARAMETER);
    104     }
    105 
    106     if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
    107     {
    108         FreeBufferOnError = TRUE;
    109     }
    110 
    111     /* Evaluate the object */
    112 
    113     Status = AcpiEvaluateObject (Handle, Pathname,
    114         ExternalParams, ReturnBuffer);
    115     if (ACPI_FAILURE (Status))
    116     {
    117         return_ACPI_STATUS (Status);
    118     }
    119 
    120     /* Type ANY means "don't care" */
    121 
    122     if (ReturnType == ACPI_TYPE_ANY)
    123     {
    124         return_ACPI_STATUS (AE_OK);
    125     }
    126 
    127     if (ReturnBuffer->Length == 0)
    128     {
    129         /* Error because caller specifically asked for a return value */
    130 
    131         ACPI_ERROR ((AE_INFO, "No return value"));
    132         return_ACPI_STATUS (AE_NULL_OBJECT);
    133     }
    134 
    135     /* Examine the object type returned from EvaluateObject */
    136 
    137     if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
    138     {
    139         return_ACPI_STATUS (AE_OK);
    140     }
    141 
    142     /* Return object type does not match requested type */
    143 
    144     ACPI_ERROR ((AE_INFO,
    145         "Incorrect return type [%s] requested [%s]",
    146         AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
    147         AcpiUtGetTypeName (ReturnType)));
    148 
    149     if (FreeBufferOnError)
    150     {
    151         /*
    152          * Free a buffer created via ACPI_ALLOCATE_BUFFER.
    153          * Note: We use AcpiOsFree here because AcpiOsAllocate was used
    154          * to allocate the buffer. This purposefully bypasses the
    155          * (optionally enabled) allocation tracking mechanism since we
    156          * only want to track internal allocations.
    157          */
    158         AcpiOsFree (ReturnBuffer->Pointer);
    159         ReturnBuffer->Pointer = NULL;
    160     }
    161 
    162     ReturnBuffer->Length = 0;
    163     return_ACPI_STATUS (AE_TYPE);
    164 }
    165 
    166 ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
    167 
    168 
    169 /*******************************************************************************
    170  *
    171  * FUNCTION:    AcpiEvaluateObject
    172  *
    173  * PARAMETERS:  Handle              - Object handle (optional)
    174  *              Pathname            - Object pathname (optional)
    175  *              ExternalParams      - List of parameters to pass to method,
    176  *                                    terminated by NULL. May be NULL
    177  *                                    if no parameters are being passed.
    178  *              ReturnBuffer        - Where to put method's return value (if
    179  *                                    any). If NULL, no value is returned.
    180  *
    181  * RETURN:      Status
    182  *
    183  * DESCRIPTION: Find and evaluate the given object, passing the given
    184  *              parameters if necessary. One of "Handle" or "Pathname" must
    185  *              be valid (non-null)
    186  *
    187  ******************************************************************************/
    188 
    189 ACPI_STATUS
    190 AcpiEvaluateObject (
    191     ACPI_HANDLE             Handle,
    192     ACPI_STRING             Pathname,
    193     ACPI_OBJECT_LIST        *ExternalParams,
    194     ACPI_BUFFER             *ReturnBuffer)
    195 {
    196     ACPI_STATUS             Status;
    197     ACPI_EVALUATE_INFO      *Info;
    198     ACPI_SIZE               BufferSpaceNeeded;
    199     UINT32                  i;
    200 
    201 
    202     ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
    203 
    204 
    205     /* Allocate and initialize the evaluation information block */
    206 
    207     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    208     if (!Info)
    209     {
    210         return_ACPI_STATUS (AE_NO_MEMORY);
    211     }
    212 
    213     /* Convert and validate the device handle */
    214 
    215     Info->PrefixNode = AcpiNsValidateHandle (Handle);
    216     if (!Info->PrefixNode)
    217     {
    218         Status = AE_BAD_PARAMETER;
    219         goto Cleanup;
    220     }
    221 
    222     /*
    223      * Get the actual namespace node for the target object.
    224      * Handles these cases:
    225      *
    226      * 1) Null node, valid pathname from root (absolute path)
    227      * 2) Node and valid pathname (path relative to Node)
    228      * 3) Node, Null pathname
    229      */
    230     if ((Pathname) &&
    231         (ACPI_IS_ROOT_PREFIX (Pathname[0])))
    232     {
    233         /* The path is fully qualified, just evaluate by name */
    234 
    235         Info->PrefixNode = NULL;
    236     }
    237     else if (!Handle)
    238     {
    239         /*
    240          * A handle is optional iff a fully qualified pathname is specified.
    241          * Since we've already handled fully qualified names above, this is
    242          * an error.
    243          */
    244         if (!Pathname)
    245         {
    246             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    247                 "Both Handle and Pathname are NULL"));
    248         }
    249         else
    250         {
    251             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    252                 "Null Handle with relative pathname [%s]", Pathname));
    253         }
    254 
    255         Status = AE_BAD_PARAMETER;
    256         goto Cleanup;
    257     }
    258 
    259     Info->RelativePathname = Pathname;
    260 
    261     /*
    262      * Convert all external objects passed as arguments to the
    263      * internal version(s).
    264      */
    265     if (ExternalParams && ExternalParams->Count)
    266     {
    267         Info->ParamCount = (UINT16) ExternalParams->Count;
    268 
    269         /* Warn on impossible argument count */
    270 
    271         if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
    272         {
    273             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
    274                 "Excess arguments (%u) - using only %u",
    275                 Info->ParamCount, ACPI_METHOD_NUM_ARGS));
    276 
    277             Info->ParamCount = ACPI_METHOD_NUM_ARGS;
    278         }
    279 
    280         /*
    281          * Allocate a new parameter block for the internal objects
    282          * Add 1 to count to allow for null terminated internal list
    283          */
    284         Info->Parameters = ACPI_ALLOCATE_ZEROED (
    285             ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
    286         if (!Info->Parameters)
    287         {
    288             Status = AE_NO_MEMORY;
    289             goto Cleanup;
    290         }
    291 
    292         /* Convert each external object in the list to an internal object */
    293 
    294         for (i = 0; i < Info->ParamCount; i++)
    295         {
    296             Status = AcpiUtCopyEobjectToIobject (
    297                 &ExternalParams->Pointer[i], &Info->Parameters[i]);
    298             if (ACPI_FAILURE (Status))
    299             {
    300                 goto Cleanup;
    301             }
    302         }
    303 
    304         Info->Parameters[Info->ParamCount] = NULL;
    305     }
    306 
    307 
    308 #ifdef _FUTURE_FEATURE
    309 
    310     /*
    311      * Begin incoming argument count analysis. Check for too few args
    312      * and too many args.
    313      */
    314     switch (AcpiNsGetType (Info->Node))
    315     {
    316     case ACPI_TYPE_METHOD:
    317 
    318         /* Check incoming argument count against the method definition */
    319 
    320         if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
    321         {
    322             ACPI_ERROR ((AE_INFO,
    323                 "Insufficient arguments (%u) - %u are required",
    324                 Info->ParamCount,
    325                 Info->ObjDesc->Method.ParamCount));
    326 
    327             Status = AE_MISSING_ARGUMENTS;
    328             goto Cleanup;
    329         }
    330 
    331         else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
    332         {
    333             ACPI_WARNING ((AE_INFO,
    334                 "Excess arguments (%u) - only %u are required",
    335                 Info->ParamCount,
    336                 Info->ObjDesc->Method.ParamCount));
    337 
    338             /* Just pass the required number of arguments */
    339 
    340             Info->ParamCount = Info->ObjDesc->Method.ParamCount;
    341         }
    342 
    343         /*
    344          * Any incoming external objects to be passed as arguments to the
    345          * method must be converted to internal objects
    346          */
    347         if (Info->ParamCount)
    348         {
    349             /*
    350              * Allocate a new parameter block for the internal objects
    351              * Add 1 to count to allow for null terminated internal list
    352              */
    353             Info->Parameters = ACPI_ALLOCATE_ZEROED (
    354                 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
    355             if (!Info->Parameters)
    356             {
    357                 Status = AE_NO_MEMORY;
    358                 goto Cleanup;
    359             }
    360 
    361             /* Convert each external object in the list to an internal object */
    362 
    363             for (i = 0; i < Info->ParamCount; i++)
    364             {
    365                 Status = AcpiUtCopyEobjectToIobject (
    366                     &ExternalParams->Pointer[i], &Info->Parameters[i]);
    367                 if (ACPI_FAILURE (Status))
    368                 {
    369                     goto Cleanup;
    370                 }
    371             }
    372 
    373             Info->Parameters[Info->ParamCount] = NULL;
    374         }
    375         break;
    376 
    377     default:
    378 
    379         /* Warn if arguments passed to an object that is not a method */
    380 
    381         if (Info->ParamCount)
    382         {
    383             ACPI_WARNING ((AE_INFO,
    384                 "%u arguments were passed to a non-method ACPI object",
    385                 Info->ParamCount));
    386         }
    387         break;
    388     }
    389 
    390 #endif
    391 
    392 
    393     /* Now we can evaluate the object */
    394 
    395     Status = AcpiNsEvaluate (Info);
    396 
    397     /*
    398      * If we are expecting a return value, and all went well above,
    399      * copy the return value to an external object.
    400      */
    401     if (!ReturnBuffer)
    402     {
    403         goto CleanupReturnObject;
    404     }
    405 
    406     if (!Info->ReturnObject)
    407     {
    408         ReturnBuffer->Length = 0;
    409         goto Cleanup;
    410     }
    411 
    412     if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
    413         ACPI_DESC_TYPE_NAMED)
    414     {
    415         /*
    416          * If we received a NS Node as a return object, this means that
    417          * the object we are evaluating has nothing interesting to
    418          * return (such as a mutex, etc.)  We return an error because
    419          * these types are essentially unsupported by this interface.
    420          * We don't check up front because this makes it easier to add
    421          * support for various types at a later date if necessary.
    422          */
    423         Status = AE_TYPE;
    424         Info->ReturnObject = NULL;   /* No need to delete a NS Node */
    425         ReturnBuffer->Length = 0;
    426     }
    427 
    428     if (ACPI_FAILURE (Status))
    429     {
    430         goto CleanupReturnObject;
    431     }
    432 
    433     /* Dereference Index and RefOf references */
    434 
    435     AcpiNsResolveReferences (Info);
    436 
    437     /* Get the size of the returned object */
    438 
    439     Status = AcpiUtGetObjectSize (Info->ReturnObject,
    440         &BufferSpaceNeeded);
    441     if (ACPI_SUCCESS (Status))
    442     {
    443         /* Validate/Allocate/Clear caller buffer */
    444 
    445         Status = AcpiUtInitializeBuffer (ReturnBuffer,
    446             BufferSpaceNeeded);
    447         if (ACPI_FAILURE (Status))
    448         {
    449             /*
    450              * Caller's buffer is too small or a new one can't
    451              * be allocated
    452              */
    453             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    454                 "Needed buffer size %X, %s\n",
    455                 (UINT32) BufferSpaceNeeded,
    456                 AcpiFormatException (Status)));
    457         }
    458         else
    459         {
    460             /* We have enough space for the object, build it */
    461 
    462             Status = AcpiUtCopyIobjectToEobject (
    463                 Info->ReturnObject, ReturnBuffer);
    464         }
    465     }
    466 
    467 CleanupReturnObject:
    468 
    469     if (Info->ReturnObject)
    470     {
    471         /*
    472          * Delete the internal return object. NOTE: Interpreter must be
    473          * locked to avoid race condition.
    474          */
    475         AcpiExEnterInterpreter ();
    476 
    477         /* Remove one reference on the return object (should delete it) */
    478 
    479         AcpiUtRemoveReference (Info->ReturnObject);
    480         AcpiExExitInterpreter ();
    481     }
    482 
    483 
    484 Cleanup:
    485 
    486     /* Free the input parameter list (if we created one) */
    487 
    488     if (Info->Parameters)
    489     {
    490         /* Free the allocated parameter block */
    491 
    492         AcpiUtDeleteInternalObjectList (Info->Parameters);
    493     }
    494 
    495     ACPI_FREE (Info);
    496     return_ACPI_STATUS (Status);
    497 }
    498 
    499 ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
    500 
    501 
    502 /*******************************************************************************
    503  *
    504  * FUNCTION:    AcpiNsResolveReferences
    505  *
    506  * PARAMETERS:  Info                    - Evaluation info block
    507  *
    508  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
    509  *
    510  * DESCRIPTION: Dereference certain reference objects. Called before an
    511  *              internal return object is converted to an external ACPI_OBJECT.
    512  *
    513  * Performs an automatic dereference of Index and RefOf reference objects.
    514  * These reference objects are not supported by the ACPI_OBJECT, so this is a
    515  * last resort effort to return something useful. Also, provides compatibility
    516  * with other ACPI implementations.
    517  *
    518  * NOTE: does not handle references within returned package objects or nested
    519  * references, but this support could be added later if found to be necessary.
    520  *
    521  ******************************************************************************/
    522 
    523 static void
    524 AcpiNsResolveReferences (
    525     ACPI_EVALUATE_INFO      *Info)
    526 {
    527     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    528     ACPI_NAMESPACE_NODE     *Node;
    529 
    530 
    531     /* We are interested in reference objects only */
    532 
    533     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
    534     {
    535         return;
    536     }
    537 
    538     /*
    539      * Two types of references are supported - those created by Index and
    540      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
    541      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
    542      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
    543      * an ACPI_OBJECT.
    544      */
    545     switch (Info->ReturnObject->Reference.Class)
    546     {
    547     case ACPI_REFCLASS_INDEX:
    548 
    549         ObjDesc = *(Info->ReturnObject->Reference.Where);
    550         break;
    551 
    552     case ACPI_REFCLASS_REFOF:
    553 
    554         Node = Info->ReturnObject->Reference.Object;
    555         if (Node)
    556         {
    557             ObjDesc = Node->Object;
    558         }
    559         break;
    560 
    561     default:
    562 
    563         return;
    564     }
    565 
    566     /* Replace the existing reference object */
    567 
    568     if (ObjDesc)
    569     {
    570         AcpiUtAddReference (ObjDesc);
    571         AcpiUtRemoveReference (Info->ReturnObject);
    572         Info->ReturnObject = ObjDesc;
    573     }
    574 
    575     return;
    576 }
    577 
    578 
    579 /*******************************************************************************
    580  *
    581  * FUNCTION:    AcpiWalkNamespace
    582  *
    583  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
    584  *              StartObject         - Handle in namespace where search begins
    585  *              MaxDepth            - Depth to which search is to reach
    586  *              DescendingCallback  - Called during tree descent
    587  *                                    when an object of "Type" is found
    588  *              AscendingCallback   - Called during tree ascent
    589  *                                    when an object of "Type" is found
    590  *              Context             - Passed to user function(s) above
    591  *              ReturnValue         - Location where return value of
    592  *                                    UserFunction is put if terminated early
    593  *
    594  * RETURNS      Return value from the UserFunction if terminated early.
    595  *              Otherwise, returns NULL.
    596  *
    597  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    598  *              starting (and ending) at the object specified by StartHandle.
    599  *              The callback function is called whenever an object that matches
    600  *              the type parameter is found. If the callback function returns
    601  *              a non-zero value, the search is terminated immediately and this
    602  *              value is returned to the caller.
    603  *
    604  *              The point of this procedure is to provide a generic namespace
    605  *              walk routine that can be called from multiple places to
    606  *              provide multiple services; the callback function(s) can be
    607  *              tailored to each task, whether it is a print function,
    608  *              a compare function, etc.
    609  *
    610  ******************************************************************************/
    611 
    612 ACPI_STATUS
    613 AcpiWalkNamespace (
    614     ACPI_OBJECT_TYPE        Type,
    615     ACPI_HANDLE             StartObject,
    616     UINT32                  MaxDepth,
    617     ACPI_WALK_CALLBACK      DescendingCallback,
    618     ACPI_WALK_CALLBACK      AscendingCallback,
    619     void                    *Context,
    620     void                    **ReturnValue)
    621 {
    622     ACPI_STATUS             Status;
    623 
    624 
    625     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
    626 
    627 
    628     /* Parameter validation */
    629 
    630     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
    631         (!MaxDepth)                  ||
    632         (!DescendingCallback && !AscendingCallback))
    633     {
    634         return_ACPI_STATUS (AE_BAD_PARAMETER);
    635     }
    636 
    637     /*
    638      * Need to acquire the namespace reader lock to prevent interference
    639      * with any concurrent table unloads (which causes the deletion of
    640      * namespace objects). We cannot allow the deletion of a namespace node
    641      * while the user function is using it. The exception to this are the
    642      * nodes created and deleted during control method execution -- these
    643      * nodes are marked as temporary nodes and are ignored by the namespace
    644      * walk. Thus, control methods can be executed while holding the
    645      * namespace deletion lock (and the user function can execute control
    646      * methods.)
    647      */
    648     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
    649     if (ACPI_FAILURE (Status))
    650     {
    651         return_ACPI_STATUS (Status);
    652     }
    653 
    654     /*
    655      * Lock the namespace around the walk. The namespace will be
    656      * unlocked/locked around each call to the user function - since the user
    657      * function must be allowed to make ACPICA calls itself (for example, it
    658      * will typically execute control methods during device enumeration.)
    659      */
    660     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    661     if (ACPI_FAILURE (Status))
    662     {
    663         goto UnlockAndExit;
    664     }
    665 
    666     /* Now we can validate the starting node */
    667 
    668     if (!AcpiNsValidateHandle (StartObject))
    669     {
    670         Status = AE_BAD_PARAMETER;
    671         goto UnlockAndExit2;
    672     }
    673 
    674     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
    675         ACPI_NS_WALK_UNLOCK, DescendingCallback,
    676         AscendingCallback, Context, ReturnValue);
    677 
    678 UnlockAndExit2:
    679     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    680 
    681 UnlockAndExit:
    682     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
    683     return_ACPI_STATUS (Status);
    684 }
    685 
    686 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
    687 
    688 
    689 /*******************************************************************************
    690  *
    691  * FUNCTION:    AcpiNsGetDeviceCallback
    692  *
    693  * PARAMETERS:  Callback from AcpiGetDevice
    694  *
    695  * RETURN:      Status
    696  *
    697  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
    698  *              present devices, or if they specified a HID, it filters based
    699  *              on that.
    700  *
    701  ******************************************************************************/
    702 
    703 static ACPI_STATUS
    704 AcpiNsGetDeviceCallback (
    705     ACPI_HANDLE             ObjHandle,
    706     UINT32                  NestingLevel,
    707     void                    *Context,
    708     void                    **ReturnValue)
    709 {
    710     ACPI_GET_DEVICES_INFO   *Info = Context;
    711     ACPI_STATUS             Status;
    712     ACPI_NAMESPACE_NODE     *Node;
    713     UINT32                  Flags;
    714     ACPI_PNP_DEVICE_ID      *Hid;
    715     ACPI_PNP_DEVICE_ID_LIST *Cid;
    716     UINT32                  i;
    717     BOOLEAN                 Found;
    718     int                     NoMatch;
    719 
    720 
    721     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    722     if (ACPI_FAILURE (Status))
    723     {
    724         return (Status);
    725     }
    726 
    727     Node = AcpiNsValidateHandle (ObjHandle);
    728     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    729     if (ACPI_FAILURE (Status))
    730     {
    731         return (Status);
    732     }
    733 
    734     if (!Node)
    735     {
    736         return (AE_BAD_PARAMETER);
    737     }
    738 
    739     /*
    740      * First, filter based on the device HID and CID.
    741      *
    742      * 01/2010: For this case where a specific HID is requested, we don't
    743      * want to run _STA until we have an actual HID match. Thus, we will
    744      * not unnecessarily execute _STA on devices for which the caller
    745      * doesn't care about. Previously, _STA was executed unconditionally
    746      * on all devices found here.
    747      *
    748      * A side-effect of this change is that now we will continue to search
    749      * for a matching HID even under device trees where the parent device
    750      * would have returned a _STA that indicates it is not present or
    751      * not functioning (thus aborting the search on that branch).
    752      */
    753     if (Info->Hid != NULL)
    754     {
    755         Status = AcpiUtExecute_HID (Node, &Hid);
    756         if (Status == AE_NOT_FOUND)
    757         {
    758             return (AE_OK);
    759         }
    760         else if (ACPI_FAILURE (Status))
    761         {
    762             return (AE_CTRL_DEPTH);
    763         }
    764 
    765         NoMatch = strcmp (Hid->String, Info->Hid);
    766         ACPI_FREE (Hid);
    767 
    768         if (NoMatch)
    769         {
    770             /*
    771              * HID does not match, attempt match within the
    772              * list of Compatible IDs (CIDs)
    773              */
    774             Status = AcpiUtExecute_CID (Node, &Cid);
    775             if (Status == AE_NOT_FOUND)
    776             {
    777                 return (AE_OK);
    778             }
    779             else if (ACPI_FAILURE (Status))
    780             {
    781                 return (AE_CTRL_DEPTH);
    782             }
    783 
    784             /* Walk the CID list */
    785 
    786             Found = FALSE;
    787             for (i = 0; i < Cid->Count; i++)
    788             {
    789                 if (strcmp (Cid->Ids[i].String, Info->Hid) == 0)
    790                 {
    791                     /* Found a matching CID */
    792 
    793                     Found = TRUE;
    794                     break;
    795                 }
    796             }
    797 
    798             ACPI_FREE (Cid);
    799             if (!Found)
    800             {
    801                 return (AE_OK);
    802             }
    803         }
    804     }
    805 
    806     /* Run _STA to determine if device is present */
    807 
    808     Status = AcpiUtExecute_STA (Node, &Flags);
    809     if (ACPI_FAILURE (Status))
    810     {
    811         return (AE_CTRL_DEPTH);
    812     }
    813 
    814     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
    815         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
    816     {
    817         /*
    818          * Don't examine the children of the device only when the
    819          * device is neither present nor functional. See ACPI spec,
    820          * description of _STA for more information.
    821          */
    822         return (AE_CTRL_DEPTH);
    823     }
    824 
    825     /* We have a valid device, invoke the user function */
    826 
    827     Status = Info->UserFunction (ObjHandle, NestingLevel,
    828         Info->Context, ReturnValue);
    829     return (Status);
    830 }
    831 
    832 
    833 /*******************************************************************************
    834  *
    835  * FUNCTION:    AcpiGetDevices
    836  *
    837  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
    838  *              UserFunction        - Called when a matching object is found
    839  *              Context             - Passed to user function
    840  *              ReturnValue         - Location where return value of
    841  *                                    UserFunction is put if terminated early
    842  *
    843  * RETURNS      Return value from the UserFunction if terminated early.
    844  *              Otherwise, returns NULL.
    845  *
    846  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    847  *              starting (and ending) at the object specified by StartHandle.
    848  *              The UserFunction is called whenever an object of type
    849  *              Device is found. If the user function returns
    850  *              a non-zero value, the search is terminated immediately and this
    851  *              value is returned to the caller.
    852  *
    853  *              This is a wrapper for WalkNamespace, but the callback performs
    854  *              additional filtering. Please see AcpiNsGetDeviceCallback.
    855  *
    856  ******************************************************************************/
    857 
    858 ACPI_STATUS
    859 AcpiGetDevices (
    860     char                    *HID,
    861     ACPI_WALK_CALLBACK      UserFunction,
    862     void                    *Context,
    863     void                    **ReturnValue)
    864 {
    865     ACPI_STATUS             Status;
    866     ACPI_GET_DEVICES_INFO   Info;
    867 
    868 
    869     ACPI_FUNCTION_TRACE (AcpiGetDevices);
    870 
    871 
    872     /* Parameter validation */
    873 
    874     if (!UserFunction)
    875     {
    876         return_ACPI_STATUS (AE_BAD_PARAMETER);
    877     }
    878 
    879     /*
    880      * We're going to call their callback from OUR callback, so we need
    881      * to know what it is, and their context parameter.
    882      */
    883     Info.Hid = HID;
    884     Info.Context = Context;
    885     Info.UserFunction = UserFunction;
    886 
    887     /*
    888      * Lock the namespace around the walk.
    889      * The namespace will be unlocked/locked around each call
    890      * to the user function - since this function
    891      * must be allowed to make Acpi calls itself.
    892      */
    893     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    894     if (ACPI_FAILURE (Status))
    895     {
    896         return_ACPI_STATUS (Status);
    897     }
    898 
    899     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
    900         ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
    901         AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
    902 
    903     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    904     return_ACPI_STATUS (Status);
    905 }
    906 
    907 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
    908 
    909 
    910 /*******************************************************************************
    911  *
    912  * FUNCTION:    AcpiAttachData
    913  *
    914  * PARAMETERS:  ObjHandle           - Namespace node
    915  *              Handler             - Handler for this attachment
    916  *              Data                - Pointer to data to be attached
    917  *
    918  * RETURN:      Status
    919  *
    920  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
    921  *
    922  ******************************************************************************/
    923 
    924 ACPI_STATUS
    925 AcpiAttachData (
    926     ACPI_HANDLE             ObjHandle,
    927     ACPI_OBJECT_HANDLER     Handler,
    928     void                    *Data)
    929 {
    930     ACPI_NAMESPACE_NODE     *Node;
    931     ACPI_STATUS             Status;
    932 
    933 
    934     /* Parameter validation */
    935 
    936     if (!ObjHandle  ||
    937         !Handler    ||
    938         !Data)
    939     {
    940         return (AE_BAD_PARAMETER);
    941     }
    942 
    943     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    944     if (ACPI_FAILURE (Status))
    945     {
    946         return (Status);
    947     }
    948 
    949     /* Convert and validate the handle */
    950 
    951     Node = AcpiNsValidateHandle (ObjHandle);
    952     if (!Node)
    953     {
    954         Status = AE_BAD_PARAMETER;
    955         goto UnlockAndExit;
    956     }
    957 
    958     Status = AcpiNsAttachData (Node, Handler, Data);
    959 
    960 UnlockAndExit:
    961     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    962     return (Status);
    963 }
    964 
    965 ACPI_EXPORT_SYMBOL (AcpiAttachData)
    966 
    967 
    968 /*******************************************************************************
    969  *
    970  * FUNCTION:    AcpiDetachData
    971  *
    972  * PARAMETERS:  ObjHandle           - Namespace node handle
    973  *              Handler             - Handler used in call to AcpiAttachData
    974  *
    975  * RETURN:      Status
    976  *
    977  * DESCRIPTION: Remove data that was previously attached to a node.
    978  *
    979  ******************************************************************************/
    980 
    981 ACPI_STATUS
    982 AcpiDetachData (
    983     ACPI_HANDLE             ObjHandle,
    984     ACPI_OBJECT_HANDLER     Handler)
    985 {
    986     ACPI_NAMESPACE_NODE     *Node;
    987     ACPI_STATUS             Status;
    988 
    989 
    990     /* Parameter validation */
    991 
    992     if (!ObjHandle  ||
    993         !Handler)
    994     {
    995         return (AE_BAD_PARAMETER);
    996     }
    997 
    998     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    999     if (ACPI_FAILURE (Status))
   1000     {
   1001         return (Status);
   1002     }
   1003 
   1004     /* Convert and validate the handle */
   1005 
   1006     Node = AcpiNsValidateHandle (ObjHandle);
   1007     if (!Node)
   1008     {
   1009         Status = AE_BAD_PARAMETER;
   1010         goto UnlockAndExit;
   1011     }
   1012 
   1013     Status = AcpiNsDetachData (Node, Handler);
   1014 
   1015 UnlockAndExit:
   1016     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1017     return (Status);
   1018 }
   1019 
   1020 ACPI_EXPORT_SYMBOL (AcpiDetachData)
   1021 
   1022 
   1023 /*******************************************************************************
   1024  *
   1025  * FUNCTION:    AcpiGetData
   1026  *
   1027  * PARAMETERS:  ObjHandle           - Namespace node
   1028  *              Handler             - Handler used in call to AttachData
   1029  *              Data                - Where the data is returned
   1030  *
   1031  * RETURN:      Status
   1032  *
   1033  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
   1034  *
   1035  ******************************************************************************/
   1036 
   1037 ACPI_STATUS
   1038 AcpiGetData (
   1039     ACPI_HANDLE             ObjHandle,
   1040     ACPI_OBJECT_HANDLER     Handler,
   1041     void                    **Data)
   1042 {
   1043     ACPI_NAMESPACE_NODE     *Node;
   1044     ACPI_STATUS             Status;
   1045 
   1046 
   1047     /* Parameter validation */
   1048 
   1049     if (!ObjHandle  ||
   1050         !Handler    ||
   1051         !Data)
   1052     {
   1053         return (AE_BAD_PARAMETER);
   1054     }
   1055 
   1056     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
   1057     if (ACPI_FAILURE (Status))
   1058     {
   1059         return (Status);
   1060     }
   1061 
   1062     /* Convert and validate the handle */
   1063 
   1064     Node = AcpiNsValidateHandle (ObjHandle);
   1065     if (!Node)
   1066     {
   1067         Status = AE_BAD_PARAMETER;
   1068         goto UnlockAndExit;
   1069     }
   1070 
   1071     Status = AcpiNsGetAttachedData (Node, Handler, Data);
   1072 
   1073 UnlockAndExit:
   1074     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1075     return (Status);
   1076 }
   1077 
   1078 ACPI_EXPORT_SYMBOL (AcpiGetData)
   1079