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