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