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