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