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