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