Home | History | Annotate | Line # | Download | only in namespace
nsxfeval.c revision 1.1.1.2
      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 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 
     46 #define __NSXFEVAL_C__
     47 
     48 #include "acpi.h"
     49 #include "accommon.h"
     50 #include "acnamesp.h"
     51 #include "acinterp.h"
     52 
     53 
     54 #define _COMPONENT          ACPI_NAMESPACE
     55         ACPI_MODULE_NAME    ("nsxfeval")
     56 
     57 /* Local prototypes */
     58 
     59 static void
     60 AcpiNsResolveReferences (
     61     ACPI_EVALUATE_INFO      *Info);
     62 
     63 
     64 /*******************************************************************************
     65  *
     66  * FUNCTION:    AcpiEvaluateObjectTyped
     67  *
     68  * PARAMETERS:  Handle              - Object handle (optional)
     69  *              Pathname            - Object pathname (optional)
     70  *              ExternalParams      - List of parameters to pass to method,
     71  *                                    terminated by NULL.  May be NULL
     72  *                                    if no parameters are being passed.
     73  *              ReturnBuffer        - Where to put method's return value (if
     74  *                                    any).  If NULL, no value is returned.
     75  *              ReturnType          - Expected type of return object
     76  *
     77  * RETURN:      Status
     78  *
     79  * DESCRIPTION: Find and evaluate the given object, passing the given
     80  *              parameters if necessary.  One of "Handle" or "Pathname" must
     81  *              be valid (non-null)
     82  *
     83  ******************************************************************************/
     84 
     85 ACPI_STATUS
     86 AcpiEvaluateObjectTyped (
     87     ACPI_HANDLE             Handle,
     88     ACPI_STRING             Pathname,
     89     ACPI_OBJECT_LIST        *ExternalParams,
     90     ACPI_BUFFER             *ReturnBuffer,
     91     ACPI_OBJECT_TYPE        ReturnType)
     92 {
     93     ACPI_STATUS             Status;
     94     BOOLEAN                 MustFree = FALSE;
     95 
     96 
     97     ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
     98 
     99 
    100     /* Return buffer must be valid */
    101 
    102     if (!ReturnBuffer)
    103     {
    104         return_ACPI_STATUS (AE_BAD_PARAMETER);
    105     }
    106 
    107     if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
    108     {
    109         MustFree = TRUE;
    110     }
    111 
    112     /* Evaluate the object */
    113 
    114     Status = AcpiEvaluateObject (Handle, Pathname, 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 (MustFree)
    150     {
    151         /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
    152 
    153         AcpiOsFree (ReturnBuffer->Pointer);
    154         ReturnBuffer->Pointer = NULL;
    155     }
    156 
    157     ReturnBuffer->Length = 0;
    158     return_ACPI_STATUS (AE_TYPE);
    159 }
    160 
    161 ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
    162 
    163 
    164 /*******************************************************************************
    165  *
    166  * FUNCTION:    AcpiEvaluateObject
    167  *
    168  * PARAMETERS:  Handle              - Object handle (optional)
    169  *              Pathname            - Object pathname (optional)
    170  *              ExternalParams      - List of parameters to pass to method,
    171  *                                    terminated by NULL.  May be NULL
    172  *                                    if no parameters are being passed.
    173  *              ReturnBuffer        - Where to put method's return value (if
    174  *                                    any).  If NULL, no value is returned.
    175  *
    176  * RETURN:      Status
    177  *
    178  * DESCRIPTION: Find and evaluate the given object, passing the given
    179  *              parameters if necessary.  One of "Handle" or "Pathname" must
    180  *              be valid (non-null)
    181  *
    182  ******************************************************************************/
    183 
    184 ACPI_STATUS
    185 AcpiEvaluateObject (
    186     ACPI_HANDLE             Handle,
    187     ACPI_STRING             Pathname,
    188     ACPI_OBJECT_LIST        *ExternalParams,
    189     ACPI_BUFFER             *ReturnBuffer)
    190 {
    191     ACPI_STATUS             Status;
    192     ACPI_EVALUATE_INFO      *Info;
    193     ACPI_SIZE               BufferSpaceNeeded;
    194     UINT32                  i;
    195 
    196 
    197     ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
    198 
    199 
    200     /* Allocate and initialize the evaluation information block */
    201 
    202     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    203     if (!Info)
    204     {
    205         return_ACPI_STATUS (AE_NO_MEMORY);
    206     }
    207 
    208     Info->Pathname = Pathname;
    209 
    210     /* Convert and validate the device handle */
    211 
    212     Info->PrefixNode = AcpiNsValidateHandle (Handle);
    213     if (!Info->PrefixNode)
    214     {
    215         Status = AE_BAD_PARAMETER;
    216         goto Cleanup;
    217     }
    218 
    219     /*
    220      * If there are parameters to be passed to a control method, the external
    221      * objects must all be converted to internal objects
    222      */
    223     if (ExternalParams && ExternalParams->Count)
    224     {
    225         /*
    226          * Allocate a new parameter block for the internal objects
    227          * Add 1 to count to allow for null terminated internal list
    228          */
    229         Info->Parameters = ACPI_ALLOCATE_ZEROED (
    230             ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
    231         if (!Info->Parameters)
    232         {
    233             Status = AE_NO_MEMORY;
    234             goto Cleanup;
    235         }
    236 
    237         /* Convert each external object in the list to an internal object */
    238 
    239         for (i = 0; i < ExternalParams->Count; i++)
    240         {
    241             Status = AcpiUtCopyEobjectToIobject (
    242                         &ExternalParams->Pointer[i], &Info->Parameters[i]);
    243             if (ACPI_FAILURE (Status))
    244             {
    245                 goto Cleanup;
    246             }
    247         }
    248         Info->Parameters[ExternalParams->Count] = NULL;
    249     }
    250 
    251     /*
    252      * Three major cases:
    253      * 1) Fully qualified pathname
    254      * 2) No handle, not fully qualified pathname (error)
    255      * 3) Valid handle
    256      */
    257     if ((Pathname) &&
    258         (AcpiNsValidRootPrefix (Pathname[0])))
    259     {
    260         /* The path is fully qualified, just evaluate by name */
    261 
    262         Info->PrefixNode = NULL;
    263         Status = AcpiNsEvaluate (Info);
    264     }
    265     else if (!Handle)
    266     {
    267         /*
    268          * A handle is optional iff a fully qualified pathname is specified.
    269          * Since we've already handled fully qualified names above, this is
    270          * an error
    271          */
    272         if (!Pathname)
    273         {
    274             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    275                 "Both Handle and Pathname are NULL"));
    276         }
    277         else
    278         {
    279             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    280                 "Null Handle with relative pathname [%s]", Pathname));
    281         }
    282 
    283         Status = AE_BAD_PARAMETER;
    284     }
    285     else
    286     {
    287         /* We have a namespace a node and a possible relative path */
    288 
    289         Status = AcpiNsEvaluate (Info);
    290     }
    291 
    292     /*
    293      * If we are expecting a return value, and all went well above,
    294      * copy the return value to an external object.
    295      */
    296     if (ReturnBuffer)
    297     {
    298         if (!Info->ReturnObject)
    299         {
    300             ReturnBuffer->Length = 0;
    301         }
    302         else
    303         {
    304             if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
    305                 ACPI_DESC_TYPE_NAMED)
    306             {
    307                 /*
    308                  * If we received a NS Node as a return object, this means that
    309                  * the object we are evaluating has nothing interesting to
    310                  * return (such as a mutex, etc.)  We return an error because
    311                  * these types are essentially unsupported by this interface.
    312                  * We don't check up front because this makes it easier to add
    313                  * support for various types at a later date if necessary.
    314                  */
    315                 Status = AE_TYPE;
    316                 Info->ReturnObject = NULL;   /* No need to delete a NS Node */
    317                 ReturnBuffer->Length = 0;
    318             }
    319 
    320             if (ACPI_SUCCESS (Status))
    321             {
    322                 /* Dereference Index and RefOf references */
    323 
    324                 AcpiNsResolveReferences (Info);
    325 
    326                 /* Get the size of the returned object */
    327 
    328                 Status = AcpiUtGetObjectSize (Info->ReturnObject,
    329                             &BufferSpaceNeeded);
    330                 if (ACPI_SUCCESS (Status))
    331                 {
    332                     /* Validate/Allocate/Clear caller buffer */
    333 
    334                     Status = AcpiUtInitializeBuffer (ReturnBuffer,
    335                                 BufferSpaceNeeded);
    336                     if (ACPI_FAILURE (Status))
    337                     {
    338                         /*
    339                          * Caller's buffer is too small or a new one can't
    340                          * be allocated
    341                          */
    342                         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    343                             "Needed buffer size %X, %s\n",
    344                             (UINT32) BufferSpaceNeeded,
    345                             AcpiFormatException (Status)));
    346                     }
    347                     else
    348                     {
    349                         /* We have enough space for the object, build it */
    350 
    351                         Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
    352                                     ReturnBuffer);
    353                     }
    354                 }
    355             }
    356         }
    357     }
    358 
    359     if (Info->ReturnObject)
    360     {
    361         /*
    362          * Delete the internal return object. NOTE: Interpreter must be
    363          * locked to avoid race condition.
    364          */
    365         AcpiExEnterInterpreter ();
    366 
    367         /* Remove one reference on the return object (should delete it) */
    368 
    369         AcpiUtRemoveReference (Info->ReturnObject);
    370         AcpiExExitInterpreter ();
    371     }
    372 
    373 
    374 Cleanup:
    375 
    376     /* Free the input parameter list (if we created one) */
    377 
    378     if (Info->Parameters)
    379     {
    380         /* Free the allocated parameter block */
    381 
    382         AcpiUtDeleteInternalObjectList (Info->Parameters);
    383     }
    384 
    385     ACPI_FREE (Info);
    386     return_ACPI_STATUS (Status);
    387 }
    388 
    389 ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
    390 
    391 
    392 /*******************************************************************************
    393  *
    394  * FUNCTION:    AcpiNsResolveReferences
    395  *
    396  * PARAMETERS:  Info                    - Evaluation info block
    397  *
    398  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
    399  *
    400  * DESCRIPTION: Dereference certain reference objects. Called before an
    401  *              internal return object is converted to an external ACPI_OBJECT.
    402  *
    403  * Performs an automatic dereference of Index and RefOf reference objects.
    404  * These reference objects are not supported by the ACPI_OBJECT, so this is a
    405  * last resort effort to return something useful. Also, provides compatibility
    406  * with other ACPI implementations.
    407  *
    408  * NOTE: does not handle references within returned package objects or nested
    409  * references, but this support could be added later if found to be necessary.
    410  *
    411  ******************************************************************************/
    412 
    413 static void
    414 AcpiNsResolveReferences (
    415     ACPI_EVALUATE_INFO      *Info)
    416 {
    417     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    418     ACPI_NAMESPACE_NODE     *Node;
    419 
    420 
    421     /* We are interested in reference objects only */
    422 
    423     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
    424     {
    425         return;
    426     }
    427 
    428     /*
    429      * Two types of references are supported - those created by Index and
    430      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
    431      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
    432      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
    433      * an ACPI_OBJECT.
    434      */
    435     switch (Info->ReturnObject->Reference.Class)
    436     {
    437     case ACPI_REFCLASS_INDEX:
    438 
    439         ObjDesc = *(Info->ReturnObject->Reference.Where);
    440         break;
    441 
    442     case ACPI_REFCLASS_REFOF:
    443 
    444         Node = Info->ReturnObject->Reference.Object;
    445         if (Node)
    446         {
    447             ObjDesc = Node->Object;
    448         }
    449         break;
    450 
    451     default:
    452         return;
    453     }
    454 
    455     /* Replace the existing reference object */
    456 
    457     if (ObjDesc)
    458     {
    459         AcpiUtAddReference (ObjDesc);
    460         AcpiUtRemoveReference (Info->ReturnObject);
    461         Info->ReturnObject = ObjDesc;
    462     }
    463 
    464     return;
    465 }
    466 
    467 
    468 /*******************************************************************************
    469  *
    470  * FUNCTION:    AcpiWalkNamespace
    471  *
    472  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
    473  *              StartObject         - Handle in namespace where search begins
    474  *              MaxDepth            - Depth to which search is to reach
    475  *              PreOrderVisit       - Called during tree pre-order visit
    476  *                                    when an object of "Type" is found
    477  *              PostOrderVisit      - Called during tree post-order visit
    478  *                                    when an object of "Type" is found
    479  *              Context             - Passed to user function(s) above
    480  *              ReturnValue         - Location where return value of
    481  *                                    UserFunction is put if terminated early
    482  *
    483  * RETURNS      Return value from the UserFunction if terminated early.
    484  *              Otherwise, returns NULL.
    485  *
    486  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    487  *              starting (and ending) at the object specified by StartHandle.
    488  *              The callback function is called whenever an object that matches
    489  *              the type parameter is found. If the callback function returns
    490  *              a non-zero value, the search is terminated immediately and this
    491  *              value is returned to the caller.
    492  *
    493  *              The point of this procedure is to provide a generic namespace
    494  *              walk routine that can be called from multiple places to
    495  *              provide multiple services; the callback function(s) can be
    496  *              tailored to each task, whether it is a print function,
    497  *              a compare function, etc.
    498  *
    499  ******************************************************************************/
    500 
    501 ACPI_STATUS
    502 AcpiWalkNamespace (
    503     ACPI_OBJECT_TYPE        Type,
    504     ACPI_HANDLE             StartObject,
    505     UINT32                  MaxDepth,
    506     ACPI_WALK_CALLBACK      PreOrderVisit,
    507     ACPI_WALK_CALLBACK      PostOrderVisit,
    508     void                    *Context,
    509     void                    **ReturnValue)
    510 {
    511     ACPI_STATUS             Status;
    512 
    513 
    514     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
    515 
    516 
    517     /* Parameter validation */
    518 
    519     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
    520         (!MaxDepth)                  ||
    521         (!PreOrderVisit && !PostOrderVisit))
    522     {
    523         return_ACPI_STATUS (AE_BAD_PARAMETER);
    524     }
    525 
    526     /*
    527      * Need to acquire the namespace reader lock to prevent interference
    528      * with any concurrent table unloads (which causes the deletion of
    529      * namespace objects). We cannot allow the deletion of a namespace node
    530      * while the user function is using it. The exception to this are the
    531      * nodes created and deleted during control method execution -- these
    532      * nodes are marked as temporary nodes and are ignored by the namespace
    533      * walk. Thus, control methods can be executed while holding the
    534      * namespace deletion lock (and the user function can execute control
    535      * methods.)
    536      */
    537     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
    538     if (ACPI_FAILURE (Status))
    539     {
    540         return (Status);
    541     }
    542 
    543     /*
    544      * Lock the namespace around the walk. The namespace will be
    545      * unlocked/locked around each call to the user function - since the user
    546      * function must be allowed to make ACPICA calls itself (for example, it
    547      * will typically execute control methods during device enumeration.)
    548      */
    549     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    550     if (ACPI_FAILURE (Status))
    551     {
    552         goto UnlockAndExit;
    553     }
    554 
    555     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
    556                 ACPI_NS_WALK_UNLOCK, PreOrderVisit,
    557                 PostOrderVisit, Context, ReturnValue);
    558 
    559     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    560 
    561 UnlockAndExit:
    562     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
    563     return_ACPI_STATUS (Status);
    564 }
    565 
    566 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
    567 
    568 
    569 /*******************************************************************************
    570  *
    571  * FUNCTION:    AcpiNsGetDeviceCallback
    572  *
    573  * PARAMETERS:  Callback from AcpiGetDevice
    574  *
    575  * RETURN:      Status
    576  *
    577  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
    578  *              present devices, or if they specified a HID, it filters based
    579  *              on that.
    580  *
    581  ******************************************************************************/
    582 
    583 static ACPI_STATUS
    584 AcpiNsGetDeviceCallback (
    585     ACPI_HANDLE             ObjHandle,
    586     UINT32                  NestingLevel,
    587     void                    *Context,
    588     void                    **ReturnValue)
    589 {
    590     ACPI_GET_DEVICES_INFO   *Info = Context;
    591     ACPI_STATUS             Status;
    592     ACPI_NAMESPACE_NODE     *Node;
    593     UINT32                  Flags;
    594     ACPI_DEVICE_ID          *Hid;
    595     ACPI_DEVICE_ID_LIST     *Cid;
    596     UINT32                  i;
    597     BOOLEAN                 Found;
    598     int                     NoMatch;
    599 
    600 
    601     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    602     if (ACPI_FAILURE (Status))
    603     {
    604         return (Status);
    605     }
    606 
    607     Node = AcpiNsValidateHandle (ObjHandle);
    608     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    609     if (ACPI_FAILURE (Status))
    610     {
    611         return (Status);
    612     }
    613 
    614     if (!Node)
    615     {
    616         return (AE_BAD_PARAMETER);
    617     }
    618 
    619     /*
    620      * First, filter based on the device HID and CID.
    621      *
    622      * 01/2010: For this case where a specific HID is requested, we don't
    623      * want to run _STA until we have an actual HID match. Thus, we will
    624      * not unnecessarily execute _STA on devices for which the caller
    625      * doesn't care about. Previously, _STA was executed unconditionally
    626      * on all devices found here.
    627      *
    628      * A side-effect of this change is that now we will continue to search
    629      * for a matching HID even under device trees where the parent device
    630      * would have returned a _STA that indicates it is not present or
    631      * not functioning (thus aborting the search on that branch).
    632      */
    633     if (Info->Hid != NULL)
    634     {
    635         Status = AcpiUtExecute_HID (Node, &Hid);
    636         if (Status == AE_NOT_FOUND)
    637         {
    638             return (AE_OK);
    639         }
    640         else if (ACPI_FAILURE (Status))
    641         {
    642             return (AE_CTRL_DEPTH);
    643         }
    644 
    645         NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
    646         ACPI_FREE (Hid);
    647 
    648         if (NoMatch)
    649         {
    650             /*
    651              * HID does not match, attempt match within the
    652              * list of Compatible IDs (CIDs)
    653              */
    654             Status = AcpiUtExecute_CID (Node, &Cid);
    655             if (Status == AE_NOT_FOUND)
    656             {
    657                 return (AE_OK);
    658             }
    659             else if (ACPI_FAILURE (Status))
    660             {
    661                 return (AE_CTRL_DEPTH);
    662             }
    663 
    664             /* Walk the CID list */
    665 
    666             Found = FALSE;
    667             for (i = 0; i < Cid->Count; i++)
    668             {
    669                 if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
    670                 {
    671                     /* Found a matching CID */
    672 
    673                     Found = TRUE;
    674                     break;
    675                 }
    676             }
    677 
    678             ACPI_FREE (Cid);
    679             if (!Found)
    680             {
    681                 return (AE_OK);
    682             }
    683         }
    684     }
    685 
    686     /* Run _STA to determine if device is present */
    687 
    688     Status = AcpiUtExecute_STA (Node, &Flags);
    689     if (ACPI_FAILURE (Status))
    690     {
    691         return (AE_CTRL_DEPTH);
    692     }
    693 
    694     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
    695         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
    696     {
    697         /*
    698          * Don't examine the children of the device only when the
    699          * device is neither present nor functional. See ACPI spec,
    700          * description of _STA for more information.
    701          */
    702         return (AE_CTRL_DEPTH);
    703     }
    704 
    705     /* We have a valid device, invoke the user function */
    706 
    707     Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
    708                 ReturnValue);
    709     return (Status);
    710 }
    711 
    712 
    713 /*******************************************************************************
    714  *
    715  * FUNCTION:    AcpiGetDevices
    716  *
    717  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
    718  *              UserFunction        - Called when a matching object is found
    719  *              Context             - Passed to user function
    720  *              ReturnValue         - Location where return value of
    721  *                                    UserFunction is put if terminated early
    722  *
    723  * RETURNS      Return value from the UserFunction if terminated early.
    724  *              Otherwise, returns NULL.
    725  *
    726  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    727  *              starting (and ending) at the object specified by StartHandle.
    728  *              The UserFunction is called whenever an object of type
    729  *              Device is found.  If the user function returns
    730  *              a non-zero value, the search is terminated immediately and this
    731  *              value is returned to the caller.
    732  *
    733  *              This is a wrapper for WalkNamespace, but the callback performs
    734  *              additional filtering. Please see AcpiNsGetDeviceCallback.
    735  *
    736  ******************************************************************************/
    737 
    738 ACPI_STATUS
    739 AcpiGetDevices (
    740     char                    *HID,
    741     ACPI_WALK_CALLBACK      UserFunction,
    742     void                    *Context,
    743     void                    **ReturnValue)
    744 {
    745     ACPI_STATUS             Status;
    746     ACPI_GET_DEVICES_INFO   Info;
    747 
    748 
    749     ACPI_FUNCTION_TRACE (AcpiGetDevices);
    750 
    751 
    752     /* Parameter validation */
    753 
    754     if (!UserFunction)
    755     {
    756         return_ACPI_STATUS (AE_BAD_PARAMETER);
    757     }
    758 
    759     /*
    760      * We're going to call their callback from OUR callback, so we need
    761      * to know what it is, and their context parameter.
    762      */
    763     Info.Hid          = HID;
    764     Info.Context      = Context;
    765     Info.UserFunction = UserFunction;
    766 
    767     /*
    768      * Lock the namespace around the walk.
    769      * The namespace will be unlocked/locked around each call
    770      * to the user function - since this function
    771      * must be allowed to make Acpi calls itself.
    772      */
    773     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    774     if (ACPI_FAILURE (Status))
    775     {
    776         return_ACPI_STATUS (Status);
    777     }
    778 
    779     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
    780                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
    781                 AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
    782 
    783     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    784     return_ACPI_STATUS (Status);
    785 }
    786 
    787 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
    788 
    789 
    790 /*******************************************************************************
    791  *
    792  * FUNCTION:    AcpiAttachData
    793  *
    794  * PARAMETERS:  ObjHandle           - Namespace node
    795  *              Handler             - Handler for this attachment
    796  *              Data                - Pointer to data to be attached
    797  *
    798  * RETURN:      Status
    799  *
    800  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
    801  *
    802  ******************************************************************************/
    803 
    804 ACPI_STATUS
    805 AcpiAttachData (
    806     ACPI_HANDLE             ObjHandle,
    807     ACPI_OBJECT_HANDLER     Handler,
    808     void                    *Data)
    809 {
    810     ACPI_NAMESPACE_NODE     *Node;
    811     ACPI_STATUS             Status;
    812 
    813 
    814     /* Parameter validation */
    815 
    816     if (!ObjHandle  ||
    817         !Handler    ||
    818         !Data)
    819     {
    820         return (AE_BAD_PARAMETER);
    821     }
    822 
    823     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    824     if (ACPI_FAILURE (Status))
    825     {
    826         return (Status);
    827     }
    828 
    829     /* Convert and validate the handle */
    830 
    831     Node = AcpiNsValidateHandle (ObjHandle);
    832     if (!Node)
    833     {
    834         Status = AE_BAD_PARAMETER;
    835         goto UnlockAndExit;
    836     }
    837 
    838     Status = AcpiNsAttachData (Node, Handler, Data);
    839 
    840 UnlockAndExit:
    841     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    842     return (Status);
    843 }
    844 
    845 ACPI_EXPORT_SYMBOL (AcpiAttachData)
    846 
    847 
    848 /*******************************************************************************
    849  *
    850  * FUNCTION:    AcpiDetachData
    851  *
    852  * PARAMETERS:  ObjHandle           - Namespace node handle
    853  *              Handler             - Handler used in call to AcpiAttachData
    854  *
    855  * RETURN:      Status
    856  *
    857  * DESCRIPTION: Remove data that was previously attached to a node.
    858  *
    859  ******************************************************************************/
    860 
    861 ACPI_STATUS
    862 AcpiDetachData (
    863     ACPI_HANDLE             ObjHandle,
    864     ACPI_OBJECT_HANDLER     Handler)
    865 {
    866     ACPI_NAMESPACE_NODE     *Node;
    867     ACPI_STATUS             Status;
    868 
    869 
    870     /* Parameter validation */
    871 
    872     if (!ObjHandle  ||
    873         !Handler)
    874     {
    875         return (AE_BAD_PARAMETER);
    876     }
    877 
    878     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    879     if (ACPI_FAILURE (Status))
    880     {
    881         return (Status);
    882     }
    883 
    884     /* Convert and validate the handle */
    885 
    886     Node = AcpiNsValidateHandle (ObjHandle);
    887     if (!Node)
    888     {
    889         Status = AE_BAD_PARAMETER;
    890         goto UnlockAndExit;
    891     }
    892 
    893     Status = AcpiNsDetachData (Node, Handler);
    894 
    895 UnlockAndExit:
    896     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    897     return (Status);
    898 }
    899 
    900 ACPI_EXPORT_SYMBOL (AcpiDetachData)
    901 
    902 
    903 /*******************************************************************************
    904  *
    905  * FUNCTION:    AcpiGetData
    906  *
    907  * PARAMETERS:  ObjHandle           - Namespace node
    908  *              Handler             - Handler used in call to AttachData
    909  *              Data                - Where the data is returned
    910  *
    911  * RETURN:      Status
    912  *
    913  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
    914  *
    915  ******************************************************************************/
    916 
    917 ACPI_STATUS
    918 AcpiGetData (
    919     ACPI_HANDLE             ObjHandle,
    920     ACPI_OBJECT_HANDLER     Handler,
    921     void                    **Data)
    922 {
    923     ACPI_NAMESPACE_NODE     *Node;
    924     ACPI_STATUS             Status;
    925 
    926 
    927     /* Parameter validation */
    928 
    929     if (!ObjHandle  ||
    930         !Handler    ||
    931         !Data)
    932     {
    933         return (AE_BAD_PARAMETER);
    934     }
    935 
    936     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    937     if (ACPI_FAILURE (Status))
    938     {
    939         return (Status);
    940     }
    941 
    942     /* Convert and validate the handle */
    943 
    944     Node = AcpiNsValidateHandle (ObjHandle);
    945     if (!Node)
    946     {
    947         Status = AE_BAD_PARAMETER;
    948         goto UnlockAndExit;
    949     }
    950 
    951     Status = AcpiNsGetAttachedData (Node, Handler, Data);
    952 
    953 UnlockAndExit:
    954     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    955     return (Status);
    956 }
    957 
    958 ACPI_EXPORT_SYMBOL (AcpiGetData)
    959 
    960 
    961