Home | History | Annotate | Line # | Download | only in namespace
nsxfeval.c revision 1.5.2.4
      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 #ifdef _FUTURE_FEATURE
    308 
    309     /*
    310      * Begin incoming argument count analysis. Check for too few args
    311      * and too many args.
    312      */
    313     switch (AcpiNsGetType (Info->Node))
    314     {
    315     case ACPI_TYPE_METHOD:
    316 
    317         /* Check incoming argument count against the method definition */
    318 
    319         if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
    320         {
    321             ACPI_ERROR ((AE_INFO,
    322                 "Insufficient arguments (%u) - %u are required",
    323                 Info->ParamCount,
    324                 Info->ObjDesc->Method.ParamCount));
    325 
    326             Status = AE_MISSING_ARGUMENTS;
    327             goto Cleanup;
    328         }
    329 
    330         else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
    331         {
    332             ACPI_WARNING ((AE_INFO,
    333                 "Excess arguments (%u) - only %u are required",
    334                 Info->ParamCount,
    335                 Info->ObjDesc->Method.ParamCount));
    336 
    337             /* Just pass the required number of arguments */
    338 
    339             Info->ParamCount = Info->ObjDesc->Method.ParamCount;
    340         }
    341 
    342         /*
    343          * Any incoming external objects to be passed as arguments to the
    344          * method must be converted to internal objects
    345          */
    346         if (Info->ParamCount)
    347         {
    348             /*
    349              * Allocate a new parameter block for the internal objects
    350              * Add 1 to count to allow for null terminated internal list
    351              */
    352             Info->Parameters = ACPI_ALLOCATE_ZEROED (
    353                 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
    354             if (!Info->Parameters)
    355             {
    356                 Status = AE_NO_MEMORY;
    357                 goto Cleanup;
    358             }
    359 
    360             /* Convert each external object in the list to an internal object */
    361 
    362             for (i = 0; i < Info->ParamCount; i++)
    363             {
    364                 Status = AcpiUtCopyEobjectToIobject (
    365                     &ExternalParams->Pointer[i], &Info->Parameters[i]);
    366                 if (ACPI_FAILURE (Status))
    367                 {
    368                     goto Cleanup;
    369                 }
    370             }
    371 
    372             Info->Parameters[Info->ParamCount] = NULL;
    373         }
    374         break;
    375 
    376     default:
    377 
    378         /* Warn if arguments passed to an object that is not a method */
    379 
    380         if (Info->ParamCount)
    381         {
    382             ACPI_WARNING ((AE_INFO,
    383                 "%u arguments were passed to a non-method ACPI object",
    384                 Info->ParamCount));
    385         }
    386         break;
    387     }
    388 
    389 #endif
    390 
    391 
    392     /* Now we can evaluate the object */
    393 
    394     Status = AcpiNsEvaluate (Info);
    395 
    396     /*
    397      * If we are expecting a return value, and all went well above,
    398      * copy the return value to an external object.
    399      */
    400     if (!ReturnBuffer)
    401     {
    402         goto CleanupReturnObject;
    403     }
    404 
    405     if (!Info->ReturnObject)
    406     {
    407         ReturnBuffer->Length = 0;
    408         goto Cleanup;
    409     }
    410 
    411     if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
    412         ACPI_DESC_TYPE_NAMED)
    413     {
    414         /*
    415          * If we received a NS Node as a return object, this means that
    416          * the object we are evaluating has nothing interesting to
    417          * return (such as a mutex, etc.)  We return an error because
    418          * these types are essentially unsupported by this interface.
    419          * We don't check up front because this makes it easier to add
    420          * support for various types at a later date if necessary.
    421          */
    422         Status = AE_TYPE;
    423         Info->ReturnObject = NULL;   /* No need to delete a NS Node */
    424         ReturnBuffer->Length = 0;
    425     }
    426 
    427     if (ACPI_FAILURE (Status))
    428     {
    429         goto CleanupReturnObject;
    430     }
    431 
    432     /* Dereference Index and RefOf references */
    433 
    434     AcpiNsResolveReferences (Info);
    435 
    436     /* Get the size of the returned object */
    437 
    438     Status = AcpiUtGetObjectSize (Info->ReturnObject,
    439         &BufferSpaceNeeded);
    440     if (ACPI_SUCCESS (Status))
    441     {
    442         /* Validate/Allocate/Clear caller buffer */
    443 
    444         Status = AcpiUtInitializeBuffer (ReturnBuffer,
    445             BufferSpaceNeeded);
    446         if (ACPI_FAILURE (Status))
    447         {
    448             /*
    449              * Caller's buffer is too small or a new one can't
    450              * be allocated
    451              */
    452             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    453                 "Needed buffer size %X, %s\n",
    454                 (UINT32) BufferSpaceNeeded,
    455                 AcpiFormatException (Status)));
    456         }
    457         else
    458         {
    459             /* We have enough space for the object, build it */
    460 
    461             Status = AcpiUtCopyIobjectToEobject (
    462                 Info->ReturnObject, ReturnBuffer);
    463         }
    464     }
    465 
    466 CleanupReturnObject:
    467 
    468     if (Info->ReturnObject)
    469     {
    470         /*
    471          * Delete the internal return object. NOTE: Interpreter must be
    472          * locked to avoid race condition.
    473          */
    474         AcpiExEnterInterpreter ();
    475 
    476         /* Remove one reference on the return object (should delete it) */
    477 
    478         AcpiUtRemoveReference (Info->ReturnObject);
    479         AcpiExExitInterpreter ();
    480     }
    481 
    482 
    483 Cleanup:
    484 
    485     /* Free the input parameter list (if we created one) */
    486 
    487     if (Info->Parameters)
    488     {
    489         /* Free the allocated parameter block */
    490 
    491         AcpiUtDeleteInternalObjectList (Info->Parameters);
    492     }
    493 
    494     ACPI_FREE (Info);
    495     return_ACPI_STATUS (Status);
    496 }
    497 
    498 ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
    499 
    500 
    501 /*******************************************************************************
    502  *
    503  * FUNCTION:    AcpiNsResolveReferences
    504  *
    505  * PARAMETERS:  Info                    - Evaluation info block
    506  *
    507  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
    508  *
    509  * DESCRIPTION: Dereference certain reference objects. Called before an
    510  *              internal return object is converted to an external ACPI_OBJECT.
    511  *
    512  * Performs an automatic dereference of Index and RefOf reference objects.
    513  * These reference objects are not supported by the ACPI_OBJECT, so this is a
    514  * last resort effort to return something useful. Also, provides compatibility
    515  * with other ACPI implementations.
    516  *
    517  * NOTE: does not handle references within returned package objects or nested
    518  * references, but this support could be added later if found to be necessary.
    519  *
    520  ******************************************************************************/
    521 
    522 static void
    523 AcpiNsResolveReferences (
    524     ACPI_EVALUATE_INFO      *Info)
    525 {
    526     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    527     ACPI_NAMESPACE_NODE     *Node;
    528 
    529 
    530     /* We are interested in reference objects only */
    531 
    532     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
    533     {
    534         return;
    535     }
    536 
    537     /*
    538      * Two types of references are supported - those created by Index and
    539      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
    540      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
    541      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
    542      * an ACPI_OBJECT.
    543      */
    544     switch (Info->ReturnObject->Reference.Class)
    545     {
    546     case ACPI_REFCLASS_INDEX:
    547 
    548         ObjDesc = *(Info->ReturnObject->Reference.Where);
    549         break;
    550 
    551     case ACPI_REFCLASS_REFOF:
    552 
    553         Node = Info->ReturnObject->Reference.Object;
    554         if (Node)
    555         {
    556             ObjDesc = Node->Object;
    557         }
    558         break;
    559 
    560     default:
    561 
    562         return;
    563     }
    564 
    565     /* Replace the existing reference object */
    566 
    567     if (ObjDesc)
    568     {
    569         AcpiUtAddReference (ObjDesc);
    570         AcpiUtRemoveReference (Info->ReturnObject);
    571         Info->ReturnObject = ObjDesc;
    572     }
    573 
    574     return;
    575 }
    576 
    577 
    578 /*******************************************************************************
    579  *
    580  * FUNCTION:    AcpiWalkNamespace
    581  *
    582  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
    583  *              StartObject         - Handle in namespace where search begins
    584  *              MaxDepth            - Depth to which search is to reach
    585  *              DescendingCallback  - Called during tree descent
    586  *                                    when an object of "Type" is found
    587  *              AscendingCallback   - Called during tree ascent
    588  *                                    when an object of "Type" is found
    589  *              Context             - Passed to user function(s) above
    590  *              ReturnValue         - Location where return value of
    591  *                                    UserFunction is put if terminated early
    592  *
    593  * RETURNS      Return value from the UserFunction if terminated early.
    594  *              Otherwise, returns NULL.
    595  *
    596  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    597  *              starting (and ending) at the object specified by StartHandle.
    598  *              The callback function is called whenever an object that matches
    599  *              the type parameter is found. If the callback function returns
    600  *              a non-zero value, the search is terminated immediately and this
    601  *              value is returned to the caller.
    602  *
    603  *              The point of this procedure is to provide a generic namespace
    604  *              walk routine that can be called from multiple places to
    605  *              provide multiple services; the callback function(s) can be
    606  *              tailored to each task, whether it is a print function,
    607  *              a compare function, etc.
    608  *
    609  ******************************************************************************/
    610 
    611 ACPI_STATUS
    612 AcpiWalkNamespace (
    613     ACPI_OBJECT_TYPE        Type,
    614     ACPI_HANDLE             StartObject,
    615     UINT32                  MaxDepth,
    616     ACPI_WALK_CALLBACK      DescendingCallback,
    617     ACPI_WALK_CALLBACK      AscendingCallback,
    618     void                    *Context,
    619     void                    **ReturnValue)
    620 {
    621     ACPI_STATUS             Status;
    622 
    623 
    624     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
    625 
    626 
    627     /* Parameter validation */
    628 
    629     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
    630         (!MaxDepth)                  ||
    631         (!DescendingCallback && !AscendingCallback))
    632     {
    633         return_ACPI_STATUS (AE_BAD_PARAMETER);
    634     }
    635 
    636     /*
    637      * Need to acquire the namespace reader lock to prevent interference
    638      * with any concurrent table unloads (which causes the deletion of
    639      * namespace objects). We cannot allow the deletion of a namespace node
    640      * while the user function is using it. The exception to this are the
    641      * nodes created and deleted during control method execution -- these
    642      * nodes are marked as temporary nodes and are ignored by the namespace
    643      * walk. Thus, control methods can be executed while holding the
    644      * namespace deletion lock (and the user function can execute control
    645      * methods.)
    646      */
    647     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
    648     if (ACPI_FAILURE (Status))
    649     {
    650         return_ACPI_STATUS (Status);
    651     }
    652 
    653     /*
    654      * Lock the namespace around the walk. The namespace will be
    655      * unlocked/locked around each call to the user function - since the user
    656      * function must be allowed to make ACPICA calls itself (for example, it
    657      * will typically execute control methods during device enumeration.)
    658      */
    659     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    660     if (ACPI_FAILURE (Status))
    661     {
    662         goto UnlockAndExit;
    663     }
    664 
    665     /* Now we can validate the starting node */
    666 
    667     if (!AcpiNsValidateHandle (StartObject))
    668     {
    669         Status = AE_BAD_PARAMETER;
    670         goto UnlockAndExit2;
    671     }
    672 
    673     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
    674         ACPI_NS_WALK_UNLOCK, DescendingCallback,
    675         AscendingCallback, Context, ReturnValue);
    676 
    677 UnlockAndExit2:
    678     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    679 
    680 UnlockAndExit:
    681     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
    682     return_ACPI_STATUS (Status);
    683 }
    684 
    685 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
    686 
    687 
    688 /*******************************************************************************
    689  *
    690  * FUNCTION:    AcpiNsGetDeviceCallback
    691  *
    692  * PARAMETERS:  Callback from AcpiGetDevice
    693  *
    694  * RETURN:      Status
    695  *
    696  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
    697  *              present devices, or if they specified a HID, it filters based
    698  *              on that.
    699  *
    700  ******************************************************************************/
    701 
    702 static ACPI_STATUS
    703 AcpiNsGetDeviceCallback (
    704     ACPI_HANDLE             ObjHandle,
    705     UINT32                  NestingLevel,
    706     void                    *Context,
    707     void                    **ReturnValue)
    708 {
    709     ACPI_GET_DEVICES_INFO   *Info = Context;
    710     ACPI_STATUS             Status;
    711     ACPI_NAMESPACE_NODE     *Node;
    712     UINT32                  Flags;
    713     ACPI_PNP_DEVICE_ID      *Hid;
    714     ACPI_PNP_DEVICE_ID_LIST *Cid;
    715     UINT32                  i;
    716     BOOLEAN                 Found;
    717     int                     NoMatch;
    718 
    719 
    720     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    721     if (ACPI_FAILURE (Status))
    722     {
    723         return (Status);
    724     }
    725 
    726     Node = AcpiNsValidateHandle (ObjHandle);
    727     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    728     if (ACPI_FAILURE (Status))
    729     {
    730         return (Status);
    731     }
    732 
    733     if (!Node)
    734     {
    735         return (AE_BAD_PARAMETER);
    736     }
    737 
    738     /*
    739      * First, filter based on the device HID and CID.
    740      *
    741      * 01/2010: For this case where a specific HID is requested, we don't
    742      * want to run _STA until we have an actual HID match. Thus, we will
    743      * not unnecessarily execute _STA on devices for which the caller
    744      * doesn't care about. Previously, _STA was executed unconditionally
    745      * on all devices found here.
    746      *
    747      * A side-effect of this change is that now we will continue to search
    748      * for a matching HID even under device trees where the parent device
    749      * would have returned a _STA that indicates it is not present or
    750      * not functioning (thus aborting the search on that branch).
    751      */
    752     if (Info->Hid != NULL)
    753     {
    754         Status = AcpiUtExecute_HID (Node, &Hid);
    755         if (Status == AE_NOT_FOUND)
    756         {
    757             return (AE_OK);
    758         }
    759         else if (ACPI_FAILURE (Status))
    760         {
    761             return (AE_CTRL_DEPTH);
    762         }
    763 
    764         NoMatch = strcmp (Hid->String, Info->Hid);
    765         ACPI_FREE (Hid);
    766 
    767         if (NoMatch)
    768         {
    769             /*
    770              * HID does not match, attempt match within the
    771              * list of Compatible IDs (CIDs)
    772              */
    773             Status = AcpiUtExecute_CID (Node, &Cid);
    774             if (Status == AE_NOT_FOUND)
    775             {
    776                 return (AE_OK);
    777             }
    778             else if (ACPI_FAILURE (Status))
    779             {
    780                 return (AE_CTRL_DEPTH);
    781             }
    782 
    783             /* Walk the CID list */
    784 
    785             Found = FALSE;
    786             for (i = 0; i < Cid->Count; i++)
    787             {
    788                 if (strcmp (Cid->Ids[i].String, Info->Hid) == 0)
    789                 {
    790                     /* Found a matching CID */
    791 
    792                     Found = TRUE;
    793                     break;
    794                 }
    795             }
    796 
    797             ACPI_FREE (Cid);
    798             if (!Found)
    799             {
    800                 return (AE_OK);
    801             }
    802         }
    803     }
    804 
    805     /* Run _STA to determine if device is present */
    806 
    807     Status = AcpiUtExecute_STA (Node, &Flags);
    808     if (ACPI_FAILURE (Status))
    809     {
    810         return (AE_CTRL_DEPTH);
    811     }
    812 
    813     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
    814         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
    815     {
    816         /*
    817          * Don't examine the children of the device only when the
    818          * device is neither present nor functional. See ACPI spec,
    819          * description of _STA for more information.
    820          */
    821         return (AE_CTRL_DEPTH);
    822     }
    823 
    824     /* We have a valid device, invoke the user function */
    825 
    826     Status = Info->UserFunction (ObjHandle, NestingLevel,
    827         Info->Context, ReturnValue);
    828     return (Status);
    829 }
    830 
    831 
    832 /*******************************************************************************
    833  *
    834  * FUNCTION:    AcpiGetDevices
    835  *
    836  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
    837  *              UserFunction        - Called when a matching object is found
    838  *              Context             - Passed to user function
    839  *              ReturnValue         - Location where return value of
    840  *                                    UserFunction is put if terminated early
    841  *
    842  * RETURNS      Return value from the UserFunction if terminated early.
    843  *              Otherwise, returns NULL.
    844  *
    845  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
    846  *              starting (and ending) at the object specified by StartHandle.
    847  *              The UserFunction is called whenever an object of type
    848  *              Device is found. If the user function returns
    849  *              a non-zero value, the search is terminated immediately and this
    850  *              value is returned to the caller.
    851  *
    852  *              This is a wrapper for WalkNamespace, but the callback performs
    853  *              additional filtering. Please see AcpiNsGetDeviceCallback.
    854  *
    855  ******************************************************************************/
    856 
    857 ACPI_STATUS
    858 AcpiGetDevices (
    859     char                    *HID,
    860     ACPI_WALK_CALLBACK      UserFunction,
    861     void                    *Context,
    862     void                    **ReturnValue)
    863 {
    864     ACPI_STATUS             Status;
    865     ACPI_GET_DEVICES_INFO   Info;
    866 
    867 
    868     ACPI_FUNCTION_TRACE (AcpiGetDevices);
    869 
    870 
    871     /* Parameter validation */
    872 
    873     if (!UserFunction)
    874     {
    875         return_ACPI_STATUS (AE_BAD_PARAMETER);
    876     }
    877 
    878     /*
    879      * We're going to call their callback from OUR callback, so we need
    880      * to know what it is, and their context parameter.
    881      */
    882     Info.Hid = HID;
    883     Info.Context = Context;
    884     Info.UserFunction = UserFunction;
    885 
    886     /*
    887      * Lock the namespace around the walk.
    888      * The namespace will be unlocked/locked around each call
    889      * to the user function - since this function
    890      * must be allowed to make Acpi calls itself.
    891      */
    892     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    893     if (ACPI_FAILURE (Status))
    894     {
    895         return_ACPI_STATUS (Status);
    896     }
    897 
    898     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
    899         ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
    900         AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
    901 
    902     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    903     return_ACPI_STATUS (Status);
    904 }
    905 
    906 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
    907 
    908 
    909 /*******************************************************************************
    910  *
    911  * FUNCTION:    AcpiAttachData
    912  *
    913  * PARAMETERS:  ObjHandle           - Namespace node
    914  *              Handler             - Handler for this attachment
    915  *              Data                - Pointer to data to be attached
    916  *
    917  * RETURN:      Status
    918  *
    919  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
    920  *
    921  ******************************************************************************/
    922 
    923 ACPI_STATUS
    924 AcpiAttachData (
    925     ACPI_HANDLE             ObjHandle,
    926     ACPI_OBJECT_HANDLER     Handler,
    927     void                    *Data)
    928 {
    929     ACPI_NAMESPACE_NODE     *Node;
    930     ACPI_STATUS             Status;
    931 
    932 
    933     /* Parameter validation */
    934 
    935     if (!ObjHandle  ||
    936         !Handler    ||
    937         !Data)
    938     {
    939         return (AE_BAD_PARAMETER);
    940     }
    941 
    942     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    943     if (ACPI_FAILURE (Status))
    944     {
    945         return (Status);
    946     }
    947 
    948     /* Convert and validate the handle */
    949 
    950     Node = AcpiNsValidateHandle (ObjHandle);
    951     if (!Node)
    952     {
    953         Status = AE_BAD_PARAMETER;
    954         goto UnlockAndExit;
    955     }
    956 
    957     Status = AcpiNsAttachData (Node, Handler, Data);
    958 
    959 UnlockAndExit:
    960     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    961     return (Status);
    962 }
    963 
    964 ACPI_EXPORT_SYMBOL (AcpiAttachData)
    965 
    966 
    967 /*******************************************************************************
    968  *
    969  * FUNCTION:    AcpiDetachData
    970  *
    971  * PARAMETERS:  ObjHandle           - Namespace node handle
    972  *              Handler             - Handler used in call to AcpiAttachData
    973  *
    974  * RETURN:      Status
    975  *
    976  * DESCRIPTION: Remove data that was previously attached to a node.
    977  *
    978  ******************************************************************************/
    979 
    980 ACPI_STATUS
    981 AcpiDetachData (
    982     ACPI_HANDLE             ObjHandle,
    983     ACPI_OBJECT_HANDLER     Handler)
    984 {
    985     ACPI_NAMESPACE_NODE     *Node;
    986     ACPI_STATUS             Status;
    987 
    988 
    989     /* Parameter validation */
    990 
    991     if (!ObjHandle  ||
    992         !Handler)
    993     {
    994         return (AE_BAD_PARAMETER);
    995     }
    996 
    997     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    998     if (ACPI_FAILURE (Status))
    999     {
   1000         return (Status);
   1001     }
   1002 
   1003     /* Convert and validate the handle */
   1004 
   1005     Node = AcpiNsValidateHandle (ObjHandle);
   1006     if (!Node)
   1007     {
   1008         Status = AE_BAD_PARAMETER;
   1009         goto UnlockAndExit;
   1010     }
   1011 
   1012     Status = AcpiNsDetachData (Node, Handler);
   1013 
   1014 UnlockAndExit:
   1015     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1016     return (Status);
   1017 }
   1018 
   1019 ACPI_EXPORT_SYMBOL (AcpiDetachData)
   1020 
   1021 
   1022 /*******************************************************************************
   1023  *
   1024  * FUNCTION:    AcpiGetData
   1025  *
   1026  * PARAMETERS:  ObjHandle           - Namespace node
   1027  *              Handler             - Handler used in call to AttachData
   1028  *              Data                - Where the data is returned
   1029  *
   1030  * RETURN:      Status
   1031  *
   1032  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
   1033  *
   1034  ******************************************************************************/
   1035 
   1036 ACPI_STATUS
   1037 AcpiGetData (
   1038     ACPI_HANDLE             ObjHandle,
   1039     ACPI_OBJECT_HANDLER     Handler,
   1040     void                    **Data)
   1041 {
   1042     ACPI_NAMESPACE_NODE     *Node;
   1043     ACPI_STATUS             Status;
   1044 
   1045 
   1046     /* Parameter validation */
   1047 
   1048     if (!ObjHandle  ||
   1049         !Handler    ||
   1050         !Data)
   1051     {
   1052         return (AE_BAD_PARAMETER);
   1053     }
   1054 
   1055     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
   1056     if (ACPI_FAILURE (Status))
   1057     {
   1058         return (Status);
   1059     }
   1060 
   1061     /* Convert and validate the handle */
   1062 
   1063     Node = AcpiNsValidateHandle (ObjHandle);
   1064     if (!Node)
   1065     {
   1066         Status = AE_BAD_PARAMETER;
   1067         goto UnlockAndExit;
   1068     }
   1069 
   1070     Status = AcpiNsGetAttachedData (Node, Handler, Data);
   1071 
   1072 UnlockAndExit:
   1073     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
   1074     return (Status);
   1075 }
   1076 
   1077 ACPI_EXPORT_SYMBOL (AcpiGetData)
   1078