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