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