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