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