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