nsxfeval.c revision 202771
1/*******************************************************************************
2 *
3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4 *                         ACPI Object evaluation interfaces
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#define __NSXFEVAL_C__
119
120#include <contrib/dev/acpica/include/acpi.h>
121#include <contrib/dev/acpica/include/accommon.h>
122#include <contrib/dev/acpica/include/acnamesp.h>
123#include <contrib/dev/acpica/include/acinterp.h>
124
125
126#define _COMPONENT          ACPI_NAMESPACE
127        ACPI_MODULE_NAME    ("nsxfeval")
128
129/* Local prototypes */
130
131static void
132AcpiNsResolveReferences (
133    ACPI_EVALUATE_INFO      *Info);
134
135
136/*******************************************************************************
137 *
138 * FUNCTION:    AcpiEvaluateObjectTyped
139 *
140 * PARAMETERS:  Handle              - Object handle (optional)
141 *              Pathname            - Object pathname (optional)
142 *              ExternalParams      - List of parameters to pass to method,
143 *                                    terminated by NULL.  May be NULL
144 *                                    if no parameters are being passed.
145 *              ReturnBuffer        - Where to put method's return value (if
146 *                                    any).  If NULL, no value is returned.
147 *              ReturnType          - Expected type of return object
148 *
149 * RETURN:      Status
150 *
151 * DESCRIPTION: Find and evaluate the given object, passing the given
152 *              parameters if necessary.  One of "Handle" or "Pathname" must
153 *              be valid (non-null)
154 *
155 ******************************************************************************/
156
157ACPI_STATUS
158AcpiEvaluateObjectTyped (
159    ACPI_HANDLE             Handle,
160    ACPI_STRING             Pathname,
161    ACPI_OBJECT_LIST        *ExternalParams,
162    ACPI_BUFFER             *ReturnBuffer,
163    ACPI_OBJECT_TYPE        ReturnType)
164{
165    ACPI_STATUS             Status;
166    BOOLEAN                 MustFree = FALSE;
167
168
169    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
170
171
172    /* Return buffer must be valid */
173
174    if (!ReturnBuffer)
175    {
176        return_ACPI_STATUS (AE_BAD_PARAMETER);
177    }
178
179    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
180    {
181        MustFree = TRUE;
182    }
183
184    /* Evaluate the object */
185
186    Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
187    if (ACPI_FAILURE (Status))
188    {
189        return_ACPI_STATUS (Status);
190    }
191
192    /* Type ANY means "don't care" */
193
194    if (ReturnType == ACPI_TYPE_ANY)
195    {
196        return_ACPI_STATUS (AE_OK);
197    }
198
199    if (ReturnBuffer->Length == 0)
200    {
201        /* Error because caller specifically asked for a return value */
202
203        ACPI_ERROR ((AE_INFO, "No return value"));
204        return_ACPI_STATUS (AE_NULL_OBJECT);
205    }
206
207    /* Examine the object type returned from EvaluateObject */
208
209    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
210    {
211        return_ACPI_STATUS (AE_OK);
212    }
213
214    /* Return object type does not match requested type */
215
216    ACPI_ERROR ((AE_INFO,
217        "Incorrect return type [%s] requested [%s]",
218        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
219        AcpiUtGetTypeName (ReturnType)));
220
221    if (MustFree)
222    {
223        /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
224
225        AcpiOsFree (ReturnBuffer->Pointer);
226        ReturnBuffer->Pointer = NULL;
227    }
228
229    ReturnBuffer->Length = 0;
230    return_ACPI_STATUS (AE_TYPE);
231}
232
233ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
234
235
236/*******************************************************************************
237 *
238 * FUNCTION:    AcpiEvaluateObject
239 *
240 * PARAMETERS:  Handle              - Object handle (optional)
241 *              Pathname            - Object pathname (optional)
242 *              ExternalParams      - List of parameters to pass to method,
243 *                                    terminated by NULL.  May be NULL
244 *                                    if no parameters are being passed.
245 *              ReturnBuffer        - Where to put method's return value (if
246 *                                    any).  If NULL, no value is returned.
247 *
248 * RETURN:      Status
249 *
250 * DESCRIPTION: Find and evaluate the given object, passing the given
251 *              parameters if necessary.  One of "Handle" or "Pathname" must
252 *              be valid (non-null)
253 *
254 ******************************************************************************/
255
256ACPI_STATUS
257AcpiEvaluateObject (
258    ACPI_HANDLE             Handle,
259    ACPI_STRING             Pathname,
260    ACPI_OBJECT_LIST        *ExternalParams,
261    ACPI_BUFFER             *ReturnBuffer)
262{
263    ACPI_STATUS             Status;
264    ACPI_EVALUATE_INFO      *Info;
265    ACPI_SIZE               BufferSpaceNeeded;
266    UINT32                  i;
267
268
269    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
270
271
272    /* Allocate and initialize the evaluation information block */
273
274    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
275    if (!Info)
276    {
277        return_ACPI_STATUS (AE_NO_MEMORY);
278    }
279
280    Info->Pathname = Pathname;
281
282    /* Convert and validate the device handle */
283
284    Info->PrefixNode = AcpiNsValidateHandle (Handle);
285    if (!Info->PrefixNode)
286    {
287        Status = AE_BAD_PARAMETER;
288        goto Cleanup;
289    }
290
291    /*
292     * If there are parameters to be passed to a control method, the external
293     * objects must all be converted to internal objects
294     */
295    if (ExternalParams && ExternalParams->Count)
296    {
297        /*
298         * Allocate a new parameter block for the internal objects
299         * Add 1 to count to allow for null terminated internal list
300         */
301        Info->Parameters = ACPI_ALLOCATE_ZEROED (
302            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
303        if (!Info->Parameters)
304        {
305            Status = AE_NO_MEMORY;
306            goto Cleanup;
307        }
308
309        /* Convert each external object in the list to an internal object */
310
311        for (i = 0; i < ExternalParams->Count; i++)
312        {
313            Status = AcpiUtCopyEobjectToIobject (
314                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
315            if (ACPI_FAILURE (Status))
316            {
317                goto Cleanup;
318            }
319        }
320        Info->Parameters[ExternalParams->Count] = NULL;
321    }
322
323    /*
324     * Three major cases:
325     * 1) Fully qualified pathname
326     * 2) No handle, not fully qualified pathname (error)
327     * 3) Valid handle
328     */
329    if ((Pathname) &&
330        (AcpiNsValidRootPrefix (Pathname[0])))
331    {
332        /* The path is fully qualified, just evaluate by name */
333
334        Info->PrefixNode = NULL;
335        Status = AcpiNsEvaluate (Info);
336    }
337    else if (!Handle)
338    {
339        /*
340         * A handle is optional iff a fully qualified pathname is specified.
341         * Since we've already handled fully qualified names above, this is
342         * an error
343         */
344        if (!Pathname)
345        {
346            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
347                "Both Handle and Pathname are NULL"));
348        }
349        else
350        {
351            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
352                "Null Handle with relative pathname [%s]", Pathname));
353        }
354
355        Status = AE_BAD_PARAMETER;
356    }
357    else
358    {
359        /* We have a namespace a node and a possible relative path */
360
361        Status = AcpiNsEvaluate (Info);
362    }
363
364    /*
365     * If we are expecting a return value, and all went well above,
366     * copy the return value to an external object.
367     */
368    if (ReturnBuffer)
369    {
370        if (!Info->ReturnObject)
371        {
372            ReturnBuffer->Length = 0;
373        }
374        else
375        {
376            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
377                ACPI_DESC_TYPE_NAMED)
378            {
379                /*
380                 * If we received a NS Node as a return object, this means that
381                 * the object we are evaluating has nothing interesting to
382                 * return (such as a mutex, etc.)  We return an error because
383                 * these types are essentially unsupported by this interface.
384                 * We don't check up front because this makes it easier to add
385                 * support for various types at a later date if necessary.
386                 */
387                Status = AE_TYPE;
388                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
389                ReturnBuffer->Length = 0;
390            }
391
392            if (ACPI_SUCCESS (Status))
393            {
394                /* Dereference Index and RefOf references */
395
396                AcpiNsResolveReferences (Info);
397
398                /* Get the size of the returned object */
399
400                Status = AcpiUtGetObjectSize (Info->ReturnObject,
401                            &BufferSpaceNeeded);
402                if (ACPI_SUCCESS (Status))
403                {
404                    /* Validate/Allocate/Clear caller buffer */
405
406                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
407                                BufferSpaceNeeded);
408                    if (ACPI_FAILURE (Status))
409                    {
410                        /*
411                         * Caller's buffer is too small or a new one can't
412                         * be allocated
413                         */
414                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
415                            "Needed buffer size %X, %s\n",
416                            (UINT32) BufferSpaceNeeded,
417                            AcpiFormatException (Status)));
418                    }
419                    else
420                    {
421                        /* We have enough space for the object, build it */
422
423                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
424                                    ReturnBuffer);
425                    }
426                }
427            }
428        }
429    }
430
431    if (Info->ReturnObject)
432    {
433        /*
434         * Delete the internal return object. NOTE: Interpreter must be
435         * locked to avoid race condition.
436         */
437        AcpiExEnterInterpreter ();
438
439        /* Remove one reference on the return object (should delete it) */
440
441        AcpiUtRemoveReference (Info->ReturnObject);
442        AcpiExExitInterpreter ();
443    }
444
445
446Cleanup:
447
448    /* Free the input parameter list (if we created one) */
449
450    if (Info->Parameters)
451    {
452        /* Free the allocated parameter block */
453
454        AcpiUtDeleteInternalObjectList (Info->Parameters);
455    }
456
457    ACPI_FREE (Info);
458    return_ACPI_STATUS (Status);
459}
460
461ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
462
463
464/*******************************************************************************
465 *
466 * FUNCTION:    AcpiNsResolveReferences
467 *
468 * PARAMETERS:  Info                    - Evaluation info block
469 *
470 * RETURN:      Info->ReturnObject is replaced with the dereferenced object
471 *
472 * DESCRIPTION: Dereference certain reference objects. Called before an
473 *              internal return object is converted to an external ACPI_OBJECT.
474 *
475 * Performs an automatic dereference of Index and RefOf reference objects.
476 * These reference objects are not supported by the ACPI_OBJECT, so this is a
477 * last resort effort to return something useful. Also, provides compatibility
478 * with other ACPI implementations.
479 *
480 * NOTE: does not handle references within returned package objects or nested
481 * references, but this support could be added later if found to be necessary.
482 *
483 ******************************************************************************/
484
485static void
486AcpiNsResolveReferences (
487    ACPI_EVALUATE_INFO      *Info)
488{
489    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
490    ACPI_NAMESPACE_NODE     *Node;
491
492
493    /* We are interested in reference objects only */
494
495    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
496    {
497        return;
498    }
499
500    /*
501     * Two types of references are supported - those created by Index and
502     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
503     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
504     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
505     * an ACPI_OBJECT.
506     */
507    switch (Info->ReturnObject->Reference.Class)
508    {
509    case ACPI_REFCLASS_INDEX:
510
511        ObjDesc = *(Info->ReturnObject->Reference.Where);
512        break;
513
514    case ACPI_REFCLASS_REFOF:
515
516        Node = Info->ReturnObject->Reference.Object;
517        if (Node)
518        {
519            ObjDesc = Node->Object;
520        }
521        break;
522
523    default:
524        return;
525    }
526
527    /* Replace the existing reference object */
528
529    if (ObjDesc)
530    {
531        AcpiUtAddReference (ObjDesc);
532        AcpiUtRemoveReference (Info->ReturnObject);
533        Info->ReturnObject = ObjDesc;
534    }
535
536    return;
537}
538
539
540/*******************************************************************************
541 *
542 * FUNCTION:    AcpiWalkNamespace
543 *
544 * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
545 *              StartObject         - Handle in namespace where search begins
546 *              MaxDepth            - Depth to which search is to reach
547 *              PreOrderVisit       - Called during tree pre-order visit
548 *                                    when an object of "Type" is found
549 *              PostOrderVisit      - Called during tree post-order visit
550 *                                    when an object of "Type" is found
551 *              Context             - Passed to user function(s) above
552 *              ReturnValue         - Location where return value of
553 *                                    UserFunction is put if terminated early
554 *
555 * RETURNS      Return value from the UserFunction if terminated early.
556 *              Otherwise, returns NULL.
557 *
558 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
559 *              starting (and ending) at the object specified by StartHandle.
560 *              The callback function is called whenever an object that matches
561 *              the type parameter is found. If the callback function returns
562 *              a non-zero value, the search is terminated immediately and this
563 *              value is returned to the caller.
564 *
565 *              The point of this procedure is to provide a generic namespace
566 *              walk routine that can be called from multiple places to
567 *              provide multiple services; the callback function(s) can be
568 *              tailored to each task, whether it is a print function,
569 *              a compare function, etc.
570 *
571 ******************************************************************************/
572
573ACPI_STATUS
574AcpiWalkNamespace (
575    ACPI_OBJECT_TYPE        Type,
576    ACPI_HANDLE             StartObject,
577    UINT32                  MaxDepth,
578    ACPI_WALK_CALLBACK      PreOrderVisit,
579    ACPI_WALK_CALLBACK      PostOrderVisit,
580    void                    *Context,
581    void                    **ReturnValue)
582{
583    ACPI_STATUS             Status;
584
585
586    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
587
588
589    /* Parameter validation */
590
591    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
592        (!MaxDepth)                  ||
593        (!PreOrderVisit && !PostOrderVisit))
594    {
595        return_ACPI_STATUS (AE_BAD_PARAMETER);
596    }
597
598    /*
599     * Need to acquire the namespace reader lock to prevent interference
600     * with any concurrent table unloads (which causes the deletion of
601     * namespace objects). We cannot allow the deletion of a namespace node
602     * while the user function is using it. The exception to this are the
603     * nodes created and deleted during control method execution -- these
604     * nodes are marked as temporary nodes and are ignored by the namespace
605     * walk. Thus, control methods can be executed while holding the
606     * namespace deletion lock (and the user function can execute control
607     * methods.)
608     */
609    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
610    if (ACPI_FAILURE (Status))
611    {
612        return (Status);
613    }
614
615    /*
616     * Lock the namespace around the walk. The namespace will be
617     * unlocked/locked around each call to the user function - since the user
618     * function must be allowed to make ACPICA calls itself (for example, it
619     * will typically execute control methods during device enumeration.)
620     */
621    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
622    if (ACPI_FAILURE (Status))
623    {
624        goto UnlockAndExit;
625    }
626
627    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
628                ACPI_NS_WALK_UNLOCK, PreOrderVisit,
629                PostOrderVisit, Context, ReturnValue);
630
631    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
632
633UnlockAndExit:
634    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
635    return_ACPI_STATUS (Status);
636}
637
638ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
639
640
641/*******************************************************************************
642 *
643 * FUNCTION:    AcpiNsGetDeviceCallback
644 *
645 * PARAMETERS:  Callback from AcpiGetDevice
646 *
647 * RETURN:      Status
648 *
649 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
650 *              present devices, or if they specified a HID, it filters based
651 *              on that.
652 *
653 ******************************************************************************/
654
655static ACPI_STATUS
656AcpiNsGetDeviceCallback (
657    ACPI_HANDLE             ObjHandle,
658    UINT32                  NestingLevel,
659    void                    *Context,
660    void                    **ReturnValue)
661{
662    ACPI_GET_DEVICES_INFO   *Info = Context;
663    ACPI_STATUS             Status;
664    ACPI_NAMESPACE_NODE     *Node;
665    UINT32                  Flags;
666    ACPI_DEVICE_ID          *Hid;
667    ACPI_DEVICE_ID_LIST     *Cid;
668    UINT32                  i;
669    BOOLEAN                 Found;
670    int                     NoMatch;
671
672
673    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
674    if (ACPI_FAILURE (Status))
675    {
676        return (Status);
677    }
678
679    Node = AcpiNsValidateHandle (ObjHandle);
680    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
681    if (ACPI_FAILURE (Status))
682    {
683        return (Status);
684    }
685
686    if (!Node)
687    {
688        return (AE_BAD_PARAMETER);
689    }
690
691    /*
692     * First, filter based on the device HID and CID.
693     *
694     * 01/2010: For this case where a specific HID is requested, we don't
695     * want to run _STA until we have an actual HID match. Thus, we will
696     * not unnecessarily execute _STA on devices for which the caller
697     * doesn't care about. Previously, _STA was executed unconditionally
698     * on all devices found here.
699     *
700     * A side-effect of this change is that now we will continue to search
701     * for a matching HID even under device trees where the parent device
702     * would have returned a _STA that indicates it is not present or
703     * not functioning (thus aborting the search on that branch).
704     */
705    if (Info->Hid != NULL)
706    {
707        Status = AcpiUtExecute_HID (Node, &Hid);
708        if (Status == AE_NOT_FOUND)
709        {
710            return (AE_OK);
711        }
712        else if (ACPI_FAILURE (Status))
713        {
714            return (AE_CTRL_DEPTH);
715        }
716
717        NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
718        ACPI_FREE (Hid);
719
720        if (NoMatch)
721        {
722            /*
723             * HID does not match, attempt match within the
724             * list of Compatible IDs (CIDs)
725             */
726            Status = AcpiUtExecute_CID (Node, &Cid);
727            if (Status == AE_NOT_FOUND)
728            {
729                return (AE_OK);
730            }
731            else if (ACPI_FAILURE (Status))
732            {
733                return (AE_CTRL_DEPTH);
734            }
735
736            /* Walk the CID list */
737
738            Found = FALSE;
739            for (i = 0; i < Cid->Count; i++)
740            {
741                if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
742                {
743                    /* Found a matching CID */
744
745                    Found = TRUE;
746                    break;
747                }
748            }
749
750            ACPI_FREE (Cid);
751            if (!Found)
752            {
753                return (AE_OK);
754            }
755        }
756    }
757
758    /* Run _STA to determine if device is present */
759
760    Status = AcpiUtExecute_STA (Node, &Flags);
761    if (ACPI_FAILURE (Status))
762    {
763        return (AE_CTRL_DEPTH);
764    }
765
766    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
767        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
768    {
769        /*
770         * Don't examine the children of the device only when the
771         * device is neither present nor functional. See ACPI spec,
772         * description of _STA for more information.
773         */
774        return (AE_CTRL_DEPTH);
775    }
776
777    /* We have a valid device, invoke the user function */
778
779    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
780                ReturnValue);
781    return (Status);
782}
783
784
785/*******************************************************************************
786 *
787 * FUNCTION:    AcpiGetDevices
788 *
789 * PARAMETERS:  HID                 - HID to search for. Can be NULL.
790 *              UserFunction        - Called when a matching object is found
791 *              Context             - Passed to user function
792 *              ReturnValue         - Location where return value of
793 *                                    UserFunction is put if terminated early
794 *
795 * RETURNS      Return value from the UserFunction if terminated early.
796 *              Otherwise, returns NULL.
797 *
798 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
799 *              starting (and ending) at the object specified by StartHandle.
800 *              The UserFunction is called whenever an object of type
801 *              Device is found.  If the user function returns
802 *              a non-zero value, the search is terminated immediately and this
803 *              value is returned to the caller.
804 *
805 *              This is a wrapper for WalkNamespace, but the callback performs
806 *              additional filtering. Please see AcpiNsGetDeviceCallback.
807 *
808 ******************************************************************************/
809
810ACPI_STATUS
811AcpiGetDevices (
812    char                    *HID,
813    ACPI_WALK_CALLBACK      UserFunction,
814    void                    *Context,
815    void                    **ReturnValue)
816{
817    ACPI_STATUS             Status;
818    ACPI_GET_DEVICES_INFO   Info;
819
820
821    ACPI_FUNCTION_TRACE (AcpiGetDevices);
822
823
824    /* Parameter validation */
825
826    if (!UserFunction)
827    {
828        return_ACPI_STATUS (AE_BAD_PARAMETER);
829    }
830
831    /*
832     * We're going to call their callback from OUR callback, so we need
833     * to know what it is, and their context parameter.
834     */
835    Info.Hid          = HID;
836    Info.Context      = Context;
837    Info.UserFunction = UserFunction;
838
839    /*
840     * Lock the namespace around the walk.
841     * The namespace will be unlocked/locked around each call
842     * to the user function - since this function
843     * must be allowed to make Acpi calls itself.
844     */
845    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
846    if (ACPI_FAILURE (Status))
847    {
848        return_ACPI_STATUS (Status);
849    }
850
851    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
852                ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
853                AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
854
855    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
856    return_ACPI_STATUS (Status);
857}
858
859ACPI_EXPORT_SYMBOL (AcpiGetDevices)
860
861
862/*******************************************************************************
863 *
864 * FUNCTION:    AcpiAttachData
865 *
866 * PARAMETERS:  ObjHandle           - Namespace node
867 *              Handler             - Handler for this attachment
868 *              Data                - Pointer to data to be attached
869 *
870 * RETURN:      Status
871 *
872 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
873 *
874 ******************************************************************************/
875
876ACPI_STATUS
877AcpiAttachData (
878    ACPI_HANDLE             ObjHandle,
879    ACPI_OBJECT_HANDLER     Handler,
880    void                    *Data)
881{
882    ACPI_NAMESPACE_NODE     *Node;
883    ACPI_STATUS             Status;
884
885
886    /* Parameter validation */
887
888    if (!ObjHandle  ||
889        !Handler    ||
890        !Data)
891    {
892        return (AE_BAD_PARAMETER);
893    }
894
895    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
896    if (ACPI_FAILURE (Status))
897    {
898        return (Status);
899    }
900
901    /* Convert and validate the handle */
902
903    Node = AcpiNsValidateHandle (ObjHandle);
904    if (!Node)
905    {
906        Status = AE_BAD_PARAMETER;
907        goto UnlockAndExit;
908    }
909
910    Status = AcpiNsAttachData (Node, Handler, Data);
911
912UnlockAndExit:
913    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
914    return (Status);
915}
916
917ACPI_EXPORT_SYMBOL (AcpiAttachData)
918
919
920/*******************************************************************************
921 *
922 * FUNCTION:    AcpiDetachData
923 *
924 * PARAMETERS:  ObjHandle           - Namespace node handle
925 *              Handler             - Handler used in call to AcpiAttachData
926 *
927 * RETURN:      Status
928 *
929 * DESCRIPTION: Remove data that was previously attached to a node.
930 *
931 ******************************************************************************/
932
933ACPI_STATUS
934AcpiDetachData (
935    ACPI_HANDLE             ObjHandle,
936    ACPI_OBJECT_HANDLER     Handler)
937{
938    ACPI_NAMESPACE_NODE     *Node;
939    ACPI_STATUS             Status;
940
941
942    /* Parameter validation */
943
944    if (!ObjHandle  ||
945        !Handler)
946    {
947        return (AE_BAD_PARAMETER);
948    }
949
950    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
951    if (ACPI_FAILURE (Status))
952    {
953        return (Status);
954    }
955
956    /* Convert and validate the handle */
957
958    Node = AcpiNsValidateHandle (ObjHandle);
959    if (!Node)
960    {
961        Status = AE_BAD_PARAMETER;
962        goto UnlockAndExit;
963    }
964
965    Status = AcpiNsDetachData (Node, Handler);
966
967UnlockAndExit:
968    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
969    return (Status);
970}
971
972ACPI_EXPORT_SYMBOL (AcpiDetachData)
973
974
975/*******************************************************************************
976 *
977 * FUNCTION:    AcpiGetData
978 *
979 * PARAMETERS:  ObjHandle           - Namespace node
980 *              Handler             - Handler used in call to AttachData
981 *              Data                - Where the data is returned
982 *
983 * RETURN:      Status
984 *
985 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
986 *
987 ******************************************************************************/
988
989ACPI_STATUS
990AcpiGetData (
991    ACPI_HANDLE             ObjHandle,
992    ACPI_OBJECT_HANDLER     Handler,
993    void                    **Data)
994{
995    ACPI_NAMESPACE_NODE     *Node;
996    ACPI_STATUS             Status;
997
998
999    /* Parameter validation */
1000
1001    if (!ObjHandle  ||
1002        !Handler    ||
1003        !Data)
1004    {
1005        return (AE_BAD_PARAMETER);
1006    }
1007
1008    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1009    if (ACPI_FAILURE (Status))
1010    {
1011        return (Status);
1012    }
1013
1014    /* Convert and validate the handle */
1015
1016    Node = AcpiNsValidateHandle (ObjHandle);
1017    if (!Node)
1018    {
1019        Status = AE_BAD_PARAMETER;
1020        goto UnlockAndExit;
1021    }
1022
1023    Status = AcpiNsGetAttachedData (Node, Handler, Data);
1024
1025UnlockAndExit:
1026    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1027    return (Status);
1028}
1029
1030ACPI_EXPORT_SYMBOL (AcpiGetData)
1031
1032
1033