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