nsxfeval.c revision 306536
1131554Stjr/*******************************************************************************
2131554Stjr *
3131554Stjr * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4131554Stjr *                         ACPI Object evaluation interfaces
5131554Stjr *
6131554Stjr ******************************************************************************/
7131554Stjr
8131554Stjr/*
9131554Stjr * Copyright (C) 2000 - 2016, Intel Corp.
10131554Stjr * All rights reserved.
11131554Stjr *
12131554Stjr * Redistribution and use in source and binary forms, with or without
13131554Stjr * modification, are permitted provided that the following conditions
14131554Stjr * are met:
15131554Stjr * 1. Redistributions of source code must retain the above copyright
16131554Stjr *    notice, this list of conditions, and the following disclaimer,
17131554Stjr *    without modification.
18131554Stjr * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19131554Stjr *    substantially similar to the "NO WARRANTY" disclaimer below
20131554Stjr *    ("Disclaimer") and any redistribution must be conditioned upon
21131554Stjr *    including a substantially similar Disclaimer requirement for further
22131554Stjr *    binary redistribution.
23131554Stjr * 3. Neither the names of the above-listed copyright holders nor the names
24131554Stjr *    of any contributors may be used to endorse or promote products derived
25131554Stjr *    from this software without specific prior written permission.
26131554Stjr *
27131554Stjr * Alternatively, this software may be distributed under the terms of the
28131554Stjr * GNU General Public License ("GPL") version 2 as published by the Free
29131554Stjr * Software Foundation.
30131554Stjr *
31131554Stjr * NO WARRANTY
32131554Stjr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33131554Stjr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34131554Stjr * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35131554Stjr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36131554Stjr * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37131554Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38131554Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39131554Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40131554Stjr * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41131554Stjr * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42131554Stjr * POSSIBILITY OF SUCH DAMAGES.
43131554Stjr */
44131554Stjr
45131554Stjr#define EXPORT_ACPI_INTERFACES
46131554Stjr
47131554Stjr#include <contrib/dev/acpica/include/acpi.h>
48131554Stjr#include <contrib/dev/acpica/include/accommon.h>
49131554Stjr#include <contrib/dev/acpica/include/acnamesp.h>
50131554Stjr#include <contrib/dev/acpica/include/acinterp.h>
51131554Stjr
52131554Stjr
53131554Stjr#define _COMPONENT          ACPI_NAMESPACE
54131554Stjr        ACPI_MODULE_NAME    ("nsxfeval")
55131554Stjr
56131554Stjr/* Local prototypes */
57131554Stjr
58131554Stjrstatic void
59131554StjrAcpiNsResolveReferences (
60131554Stjr    ACPI_EVALUATE_INFO      *Info);
61131554Stjr
62131554Stjr
63131554Stjr/*******************************************************************************
64131554Stjr *
65131554Stjr * FUNCTION:    AcpiEvaluateObjectTyped
66131554Stjr *
67131554Stjr * PARAMETERS:  Handle              - Object handle (optional)
68131554Stjr *              Pathname            - Object pathname (optional)
69131554Stjr *              ExternalParams      - List of parameters to pass to method,
70131554Stjr *                                    terminated by NULL. May be NULL
71131554Stjr *                                    if no parameters are being passed.
72131554Stjr *              ReturnBuffer        - Where to put method's return value (if
73131554Stjr *                                    any). If NULL, no value is returned.
74131554Stjr *              ReturnType          - Expected type of return object
75131554Stjr *
76131554Stjr * RETURN:      Status
77131554Stjr *
78131554Stjr * DESCRIPTION: Find and evaluate the given object, passing the given
79131554Stjr *              parameters if necessary. One of "Handle" or "Pathname" must
80131554Stjr *              be valid (non-null)
81131554Stjr *
82131554Stjr ******************************************************************************/
83131554Stjr
84131554StjrACPI_STATUS
85131554StjrAcpiEvaluateObjectTyped (
86131554Stjr    ACPI_HANDLE             Handle,
87131554Stjr    ACPI_STRING             Pathname,
88131554Stjr    ACPI_OBJECT_LIST        *ExternalParams,
89131554Stjr    ACPI_BUFFER             *ReturnBuffer,
90131554Stjr    ACPI_OBJECT_TYPE        ReturnType)
91131554Stjr{
92131554Stjr    ACPI_STATUS             Status;
93131554Stjr    BOOLEAN                 FreeBufferOnError = FALSE;
94131554Stjr
95131554Stjr
96131554Stjr    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
97131554Stjr
98131554Stjr
99131554Stjr    /* Return buffer must be valid */
100131554Stjr
101131554Stjr    if (!ReturnBuffer)
102131554Stjr    {
103131554Stjr        return_ACPI_STATUS (AE_BAD_PARAMETER);
104131554Stjr    }
105131554Stjr
106131554Stjr    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
107131554Stjr    {
108131554Stjr        FreeBufferOnError = TRUE;
109131554Stjr    }
110131554Stjr
111131554Stjr    /* Evaluate the object */
112131554Stjr
113131554Stjr    Status = AcpiEvaluateObject (Handle, Pathname,
114131554Stjr        ExternalParams, ReturnBuffer);
115131554Stjr    if (ACPI_FAILURE (Status))
116131554Stjr    {
117131554Stjr        return_ACPI_STATUS (Status);
118131554Stjr    }
119131554Stjr
120131554Stjr    /* Type ANY means "don't care" */
121131554Stjr
122131554Stjr    if (ReturnType == ACPI_TYPE_ANY)
123131554Stjr    {
124131554Stjr        return_ACPI_STATUS (AE_OK);
125131554Stjr    }
126131554Stjr
127131554Stjr    if (ReturnBuffer->Length == 0)
128131554Stjr    {
129131554Stjr        /* Error because caller specifically asked for a return value */
130131554Stjr
131131554Stjr        ACPI_ERROR ((AE_INFO, "No return value"));
132131554Stjr        return_ACPI_STATUS (AE_NULL_OBJECT);
133131554Stjr    }
134131554Stjr
135131554Stjr    /* Examine the object type returned from EvaluateObject */
136131554Stjr
137131554Stjr    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
138131554Stjr    {
139131554Stjr        return_ACPI_STATUS (AE_OK);
140131554Stjr    }
141131554Stjr
142131554Stjr    /* Return object type does not match requested type */
143131554Stjr
144131554Stjr    ACPI_ERROR ((AE_INFO,
145131554Stjr        "Incorrect return type [%s] requested [%s]",
146131554Stjr        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
147131554Stjr        AcpiUtGetTypeName (ReturnType)));
148131554Stjr
149131554Stjr    if (FreeBufferOnError)
150131554Stjr    {
151131554Stjr        /*
152131554Stjr         * Free a buffer created via ACPI_ALLOCATE_BUFFER.
153131554Stjr         * Note: We use AcpiOsFree here because AcpiOsAllocate was used
154131554Stjr         * to allocate the buffer. This purposefully bypasses the
155131554Stjr         * (optionally enabled) allocation tracking mechanism since we
156131554Stjr         * only want to track internal allocations.
157131554Stjr         */
158131554Stjr        AcpiOsFree (ReturnBuffer->Pointer);
159131554Stjr        ReturnBuffer->Pointer = NULL;
160131554Stjr    }
161131554Stjr
162131554Stjr    ReturnBuffer->Length = 0;
163131554Stjr    return_ACPI_STATUS (AE_TYPE);
164131554Stjr}
165131554Stjr
166131554StjrACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
167131554Stjr
168131554Stjr
169131554Stjr/*******************************************************************************
170131554Stjr *
171131554Stjr * FUNCTION:    AcpiEvaluateObject
172131554Stjr *
173131554Stjr * PARAMETERS:  Handle              - Object handle (optional)
174131554Stjr *              Pathname            - Object pathname (optional)
175131554Stjr *              ExternalParams      - List of parameters to pass to method,
176131554Stjr *                                    terminated by NULL. May be NULL
177131554Stjr *                                    if no parameters are being passed.
178131554Stjr *              ReturnBuffer        - Where to put method's return value (if
179131554Stjr *                                    any). If NULL, no value is returned.
180131554Stjr *
181131554Stjr * RETURN:      Status
182131554Stjr *
183131554Stjr * DESCRIPTION: Find and evaluate the given object, passing the given
184131554Stjr *              parameters if necessary. One of "Handle" or "Pathname" must
185131554Stjr *              be valid (non-null)
186131554Stjr *
187131554Stjr ******************************************************************************/
188131554Stjr
189131554StjrACPI_STATUS
190131554StjrAcpiEvaluateObject (
191131554Stjr    ACPI_HANDLE             Handle,
192131554Stjr    ACPI_STRING             Pathname,
193131554Stjr    ACPI_OBJECT_LIST        *ExternalParams,
194131554Stjr    ACPI_BUFFER             *ReturnBuffer)
195131554Stjr{
196131554Stjr    ACPI_STATUS             Status;
197131554Stjr    ACPI_EVALUATE_INFO      *Info;
198131554Stjr    ACPI_SIZE               BufferSpaceNeeded;
199131554Stjr    UINT32                  i;
200131554Stjr
201131554Stjr
202131554Stjr    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
203131554Stjr
204131554Stjr
205131554Stjr    /* Allocate and initialize the evaluation information block */
206131554Stjr
207131554Stjr    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
208131554Stjr    if (!Info)
209131554Stjr    {
210131554Stjr        return_ACPI_STATUS (AE_NO_MEMORY);
211131554Stjr    }
212131554Stjr
213131554Stjr    /* Convert and validate the device handle */
214131554Stjr
215131554Stjr    Info->PrefixNode = AcpiNsValidateHandle (Handle);
216131554Stjr    if (!Info->PrefixNode)
217131554Stjr    {
218131554Stjr        Status = AE_BAD_PARAMETER;
219131554Stjr        goto Cleanup;
220131554Stjr    }
221131554Stjr
222131554Stjr    /*
223131554Stjr     * Get the actual namespace node for the target object.
224131554Stjr     * Handles these cases:
225131554Stjr     *
226131554Stjr     * 1) Null node, valid pathname from root (absolute path)
227131554Stjr     * 2) Node and valid pathname (path relative to Node)
228131554Stjr     * 3) Node, Null pathname
229131554Stjr     */
230131554Stjr    if ((Pathname) &&
231131554Stjr        (ACPI_IS_ROOT_PREFIX (Pathname[0])))
232131554Stjr    {
233131554Stjr        /* The path is fully qualified, just evaluate by name */
234131554Stjr
235131554Stjr        Info->PrefixNode = NULL;
236131554Stjr    }
237131554Stjr    else if (!Handle)
238131554Stjr    {
239131554Stjr        /*
240131554Stjr         * A handle is optional iff a fully qualified pathname is specified.
241131554Stjr         * Since we've already handled fully qualified names above, this is
242131554Stjr         * an error.
243131554Stjr         */
244131554Stjr        if (!Pathname)
245131554Stjr        {
246131554Stjr            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
247131554Stjr                "Both Handle and Pathname are NULL"));
248131554Stjr        }
249131554Stjr        else
250131554Stjr        {
251131554Stjr            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
252131554Stjr                "Null Handle with relative pathname [%s]", Pathname));
253131554Stjr        }
254131554Stjr
255131554Stjr        Status = AE_BAD_PARAMETER;
256131554Stjr        goto Cleanup;
257131554Stjr    }
258131554Stjr
259131554Stjr    Info->RelativePathname = Pathname;
260131554Stjr
261131554Stjr    /*
262131554Stjr     * Convert all external objects passed as arguments to the
263131554Stjr     * internal version(s).
264131554Stjr     */
265131554Stjr    if (ExternalParams && ExternalParams->Count)
266131554Stjr    {
267131554Stjr        Info->ParamCount = (UINT16) ExternalParams->Count;
268131554Stjr
269131554Stjr        /* Warn on impossible argument count */
270131554Stjr
271131554Stjr        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
272131554Stjr        {
273131554Stjr            ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
274131554Stjr                "Excess arguments (%u) - using only %u",
275131554Stjr                Info->ParamCount, ACPI_METHOD_NUM_ARGS));
276131554Stjr
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#ifdef _FUTURE_FEATURE
309
310    /*
311     * Begin incoming argument count analysis. Check for too few args
312     * and too many args.
313     */
314    switch (AcpiNsGetType (Info->Node))
315    {
316    case ACPI_TYPE_METHOD:
317
318        /* Check incoming argument count against the method definition */
319
320        if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
321        {
322            ACPI_ERROR ((AE_INFO,
323                "Insufficient arguments (%u) - %u are required",
324                Info->ParamCount,
325                Info->ObjDesc->Method.ParamCount));
326
327            Status = AE_MISSING_ARGUMENTS;
328            goto Cleanup;
329        }
330
331        else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
332        {
333            ACPI_WARNING ((AE_INFO,
334                "Excess arguments (%u) - only %u are required",
335                Info->ParamCount,
336                Info->ObjDesc->Method.ParamCount));
337
338            /* Just pass the required number of arguments */
339
340            Info->ParamCount = Info->ObjDesc->Method.ParamCount;
341        }
342
343        /*
344         * Any incoming external objects to be passed as arguments to the
345         * method must be converted to internal objects
346         */
347        if (Info->ParamCount)
348        {
349            /*
350             * Allocate a new parameter block for the internal objects
351             * Add 1 to count to allow for null terminated internal list
352             */
353            Info->Parameters = ACPI_ALLOCATE_ZEROED (
354                ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
355            if (!Info->Parameters)
356            {
357                Status = AE_NO_MEMORY;
358                goto Cleanup;
359            }
360
361            /* Convert each external object in the list to an internal object */
362
363            for (i = 0; i < Info->ParamCount; i++)
364            {
365                Status = AcpiUtCopyEobjectToIobject (
366                    &ExternalParams->Pointer[i], &Info->Parameters[i]);
367                if (ACPI_FAILURE (Status))
368                {
369                    goto Cleanup;
370                }
371            }
372
373            Info->Parameters[Info->ParamCount] = NULL;
374        }
375        break;
376
377    default:
378
379        /* Warn if arguments passed to an object that is not a method */
380
381        if (Info->ParamCount)
382        {
383            ACPI_WARNING ((AE_INFO,
384                "%u arguments were passed to a non-method ACPI object",
385                Info->ParamCount));
386        }
387        break;
388    }
389
390#endif
391
392
393    /* Now we can evaluate the object */
394
395    Status = AcpiNsEvaluate (Info);
396
397    /*
398     * If we are expecting a return value, and all went well above,
399     * copy the return value to an external object.
400     */
401    if (!ReturnBuffer)
402    {
403        goto CleanupReturnObject;
404    }
405
406    if (!Info->ReturnObject)
407    {
408        ReturnBuffer->Length = 0;
409        goto Cleanup;
410    }
411
412    if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
413        ACPI_DESC_TYPE_NAMED)
414    {
415        /*
416         * If we received a NS Node as a return object, this means that
417         * the object we are evaluating has nothing interesting to
418         * return (such as a mutex, etc.)  We return an error because
419         * these types are essentially unsupported by this interface.
420         * We don't check up front because this makes it easier to add
421         * support for various types at a later date if necessary.
422         */
423        Status = AE_TYPE;
424        Info->ReturnObject = NULL;   /* No need to delete a NS Node */
425        ReturnBuffer->Length = 0;
426    }
427
428    if (ACPI_FAILURE (Status))
429    {
430        goto CleanupReturnObject;
431    }
432
433    /* Dereference Index and RefOf references */
434
435    AcpiNsResolveReferences (Info);
436
437    /* Get the size of the returned object */
438
439    Status = AcpiUtGetObjectSize (Info->ReturnObject,
440        &BufferSpaceNeeded);
441    if (ACPI_SUCCESS (Status))
442    {
443        /* Validate/Allocate/Clear caller buffer */
444
445        Status = AcpiUtInitializeBuffer (ReturnBuffer,
446            BufferSpaceNeeded);
447        if (ACPI_FAILURE (Status))
448        {
449            /*
450             * Caller's buffer is too small or a new one can't
451             * be allocated
452             */
453            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
454                "Needed buffer size %X, %s\n",
455                (UINT32) BufferSpaceNeeded,
456                AcpiFormatException (Status)));
457        }
458        else
459        {
460            /* We have enough space for the object, build it */
461
462            Status = AcpiUtCopyIobjectToEobject (
463                Info->ReturnObject, ReturnBuffer);
464        }
465    }
466
467CleanupReturnObject:
468
469    if (Info->ReturnObject)
470    {
471        /*
472         * Delete the internal return object. NOTE: Interpreter must be
473         * locked to avoid race condition.
474         */
475        AcpiExEnterInterpreter ();
476
477        /* Remove one reference on the return object (should delete it) */
478
479        AcpiUtRemoveReference (Info->ReturnObject);
480        AcpiExExitInterpreter ();
481    }
482
483
484Cleanup:
485
486    /* Free the input parameter list (if we created one) */
487
488    if (Info->Parameters)
489    {
490        /* Free the allocated parameter block */
491
492        AcpiUtDeleteInternalObjectList (Info->Parameters);
493    }
494
495    ACPI_FREE (Info);
496    return_ACPI_STATUS (Status);
497}
498
499ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
500
501
502/*******************************************************************************
503 *
504 * FUNCTION:    AcpiNsResolveReferences
505 *
506 * PARAMETERS:  Info                    - Evaluation info block
507 *
508 * RETURN:      Info->ReturnObject is replaced with the dereferenced object
509 *
510 * DESCRIPTION: Dereference certain reference objects. Called before an
511 *              internal return object is converted to an external ACPI_OBJECT.
512 *
513 * Performs an automatic dereference of Index and RefOf reference objects.
514 * These reference objects are not supported by the ACPI_OBJECT, so this is a
515 * last resort effort to return something useful. Also, provides compatibility
516 * with other ACPI implementations.
517 *
518 * NOTE: does not handle references within returned package objects or nested
519 * references, but this support could be added later if found to be necessary.
520 *
521 ******************************************************************************/
522
523static void
524AcpiNsResolveReferences (
525    ACPI_EVALUATE_INFO      *Info)
526{
527    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
528    ACPI_NAMESPACE_NODE     *Node;
529
530
531    /* We are interested in reference objects only */
532
533    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
534    {
535        return;
536    }
537
538    /*
539     * Two types of references are supported - those created by Index and
540     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
541     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
542     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
543     * an ACPI_OBJECT.
544     */
545    switch (Info->ReturnObject->Reference.Class)
546    {
547    case ACPI_REFCLASS_INDEX:
548
549        ObjDesc = *(Info->ReturnObject->Reference.Where);
550        break;
551
552    case ACPI_REFCLASS_REFOF:
553
554        Node = Info->ReturnObject->Reference.Object;
555        if (Node)
556        {
557            ObjDesc = Node->Object;
558        }
559        break;
560
561    default:
562
563        return;
564    }
565
566    /* Replace the existing reference object */
567
568    if (ObjDesc)
569    {
570        AcpiUtAddReference (ObjDesc);
571        AcpiUtRemoveReference (Info->ReturnObject);
572        Info->ReturnObject = ObjDesc;
573    }
574
575    return;
576}
577
578
579/*******************************************************************************
580 *
581 * FUNCTION:    AcpiWalkNamespace
582 *
583 * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
584 *              StartObject         - Handle in namespace where search begins
585 *              MaxDepth            - Depth to which search is to reach
586 *              DescendingCallback  - Called during tree descent
587 *                                    when an object of "Type" is found
588 *              AscendingCallback   - Called during tree ascent
589 *                                    when an object of "Type" is found
590 *              Context             - Passed to user function(s) above
591 *              ReturnValue         - Location where return value of
592 *                                    UserFunction is put if terminated early
593 *
594 * RETURNS      Return value from the UserFunction if terminated early.
595 *              Otherwise, returns NULL.
596 *
597 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
598 *              starting (and ending) at the object specified by StartHandle.
599 *              The callback function is called whenever an object that matches
600 *              the type parameter is found. If the callback function returns
601 *              a non-zero value, the search is terminated immediately and this
602 *              value is returned to the caller.
603 *
604 *              The point of this procedure is to provide a generic namespace
605 *              walk routine that can be called from multiple places to
606 *              provide multiple services; the callback function(s) can be
607 *              tailored to each task, whether it is a print function,
608 *              a compare function, etc.
609 *
610 ******************************************************************************/
611
612ACPI_STATUS
613AcpiWalkNamespace (
614    ACPI_OBJECT_TYPE        Type,
615    ACPI_HANDLE             StartObject,
616    UINT32                  MaxDepth,
617    ACPI_WALK_CALLBACK      DescendingCallback,
618    ACPI_WALK_CALLBACK      AscendingCallback,
619    void                    *Context,
620    void                    **ReturnValue)
621{
622    ACPI_STATUS             Status;
623
624
625    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
626
627
628    /* Parameter validation */
629
630    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
631        (!MaxDepth)                  ||
632        (!DescendingCallback && !AscendingCallback))
633    {
634        return_ACPI_STATUS (AE_BAD_PARAMETER);
635    }
636
637    /*
638     * Need to acquire the namespace reader lock to prevent interference
639     * with any concurrent table unloads (which causes the deletion of
640     * namespace objects). We cannot allow the deletion of a namespace node
641     * while the user function is using it. The exception to this are the
642     * nodes created and deleted during control method execution -- these
643     * nodes are marked as temporary nodes and are ignored by the namespace
644     * walk. Thus, control methods can be executed while holding the
645     * namespace deletion lock (and the user function can execute control
646     * methods.)
647     */
648    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
649    if (ACPI_FAILURE (Status))
650    {
651        return_ACPI_STATUS (Status);
652    }
653
654    /*
655     * Lock the namespace around the walk. The namespace will be
656     * unlocked/locked around each call to the user function - since the user
657     * function must be allowed to make ACPICA calls itself (for example, it
658     * will typically execute control methods during device enumeration.)
659     */
660    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
661    if (ACPI_FAILURE (Status))
662    {
663        goto UnlockAndExit;
664    }
665
666    /* Now we can validate the starting node */
667
668    if (!AcpiNsValidateHandle (StartObject))
669    {
670        Status = AE_BAD_PARAMETER;
671        goto UnlockAndExit2;
672    }
673
674    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
675        ACPI_NS_WALK_UNLOCK, DescendingCallback,
676        AscendingCallback, Context, ReturnValue);
677
678UnlockAndExit2:
679    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
680
681UnlockAndExit:
682    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
683    return_ACPI_STATUS (Status);
684}
685
686ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
687
688
689/*******************************************************************************
690 *
691 * FUNCTION:    AcpiNsGetDeviceCallback
692 *
693 * PARAMETERS:  Callback from AcpiGetDevice
694 *
695 * RETURN:      Status
696 *
697 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
698 *              present devices, or if they specified a HID, it filters based
699 *              on that.
700 *
701 ******************************************************************************/
702
703static ACPI_STATUS
704AcpiNsGetDeviceCallback (
705    ACPI_HANDLE             ObjHandle,
706    UINT32                  NestingLevel,
707    void                    *Context,
708    void                    **ReturnValue)
709{
710    ACPI_GET_DEVICES_INFO   *Info = Context;
711    ACPI_STATUS             Status;
712    ACPI_NAMESPACE_NODE     *Node;
713    UINT32                  Flags;
714    ACPI_PNP_DEVICE_ID      *Hid;
715    ACPI_PNP_DEVICE_ID_LIST *Cid;
716    UINT32                  i;
717    BOOLEAN                 Found;
718    int                     NoMatch;
719
720
721    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
722    if (ACPI_FAILURE (Status))
723    {
724        return (Status);
725    }
726
727    Node = AcpiNsValidateHandle (ObjHandle);
728    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
729    if (ACPI_FAILURE (Status))
730    {
731        return (Status);
732    }
733
734    if (!Node)
735    {
736        return (AE_BAD_PARAMETER);
737    }
738
739    /*
740     * First, filter based on the device HID and CID.
741     *
742     * 01/2010: For this case where a specific HID is requested, we don't
743     * want to run _STA until we have an actual HID match. Thus, we will
744     * not unnecessarily execute _STA on devices for which the caller
745     * doesn't care about. Previously, _STA was executed unconditionally
746     * on all devices found here.
747     *
748     * A side-effect of this change is that now we will continue to search
749     * for a matching HID even under device trees where the parent device
750     * would have returned a _STA that indicates it is not present or
751     * not functioning (thus aborting the search on that branch).
752     */
753    if (Info->Hid != NULL)
754    {
755        Status = AcpiUtExecute_HID (Node, &Hid);
756        if (Status == AE_NOT_FOUND)
757        {
758            return (AE_OK);
759        }
760        else if (ACPI_FAILURE (Status))
761        {
762            return (AE_CTRL_DEPTH);
763        }
764
765        NoMatch = strcmp (Hid->String, Info->Hid);
766        ACPI_FREE (Hid);
767
768        if (NoMatch)
769        {
770            /*
771             * HID does not match, attempt match within the
772             * list of Compatible IDs (CIDs)
773             */
774            Status = AcpiUtExecute_CID (Node, &Cid);
775            if (Status == AE_NOT_FOUND)
776            {
777                return (AE_OK);
778            }
779            else if (ACPI_FAILURE (Status))
780            {
781                return (AE_CTRL_DEPTH);
782            }
783
784            /* Walk the CID list */
785
786            Found = FALSE;
787            for (i = 0; i < Cid->Count; i++)
788            {
789                if (strcmp (Cid->Ids[i].String, Info->Hid) == 0)
790                {
791                    /* Found a matching CID */
792
793                    Found = TRUE;
794                    break;
795                }
796            }
797
798            ACPI_FREE (Cid);
799            if (!Found)
800            {
801                return (AE_OK);
802            }
803        }
804    }
805
806    /* Run _STA to determine if device is present */
807
808    Status = AcpiUtExecute_STA (Node, &Flags);
809    if (ACPI_FAILURE (Status))
810    {
811        return (AE_CTRL_DEPTH);
812    }
813
814    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
815        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
816    {
817        /*
818         * Don't examine the children of the device only when the
819         * device is neither present nor functional. See ACPI spec,
820         * description of _STA for more information.
821         */
822        return (AE_CTRL_DEPTH);
823    }
824
825    /* We have a valid device, invoke the user function */
826
827    Status = Info->UserFunction (ObjHandle, NestingLevel,
828        Info->Context, ReturnValue);
829    return (Status);
830}
831
832
833/*******************************************************************************
834 *
835 * FUNCTION:    AcpiGetDevices
836 *
837 * PARAMETERS:  HID                 - HID to search for. Can be NULL.
838 *              UserFunction        - Called when a matching object is found
839 *              Context             - Passed to user function
840 *              ReturnValue         - Location where return value of
841 *                                    UserFunction is put if terminated early
842 *
843 * RETURNS      Return value from the UserFunction if terminated early.
844 *              Otherwise, returns NULL.
845 *
846 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
847 *              starting (and ending) at the object specified by StartHandle.
848 *              The UserFunction is called whenever an object of type
849 *              Device is found. If the user function returns
850 *              a non-zero value, the search is terminated immediately and this
851 *              value is returned to the caller.
852 *
853 *              This is a wrapper for WalkNamespace, but the callback performs
854 *              additional filtering. Please see AcpiNsGetDeviceCallback.
855 *
856 ******************************************************************************/
857
858ACPI_STATUS
859AcpiGetDevices (
860    char                    *HID,
861    ACPI_WALK_CALLBACK      UserFunction,
862    void                    *Context,
863    void                    **ReturnValue)
864{
865    ACPI_STATUS             Status;
866    ACPI_GET_DEVICES_INFO   Info;
867
868
869    ACPI_FUNCTION_TRACE (AcpiGetDevices);
870
871
872    /* Parameter validation */
873
874    if (!UserFunction)
875    {
876        return_ACPI_STATUS (AE_BAD_PARAMETER);
877    }
878
879    /*
880     * We're going to call their callback from OUR callback, so we need
881     * to know what it is, and their context parameter.
882     */
883    Info.Hid = HID;
884    Info.Context = Context;
885    Info.UserFunction = UserFunction;
886
887    /*
888     * Lock the namespace around the walk.
889     * The namespace will be unlocked/locked around each call
890     * to the user function - since this function
891     * must be allowed to make Acpi calls itself.
892     */
893    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
894    if (ACPI_FAILURE (Status))
895    {
896        return_ACPI_STATUS (Status);
897    }
898
899    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
900        ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
901        AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
902
903    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
904    return_ACPI_STATUS (Status);
905}
906
907ACPI_EXPORT_SYMBOL (AcpiGetDevices)
908
909
910/*******************************************************************************
911 *
912 * FUNCTION:    AcpiAttachData
913 *
914 * PARAMETERS:  ObjHandle           - Namespace node
915 *              Handler             - Handler for this attachment
916 *              Data                - Pointer to data to be attached
917 *
918 * RETURN:      Status
919 *
920 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
921 *
922 ******************************************************************************/
923
924ACPI_STATUS
925AcpiAttachData (
926    ACPI_HANDLE             ObjHandle,
927    ACPI_OBJECT_HANDLER     Handler,
928    void                    *Data)
929{
930    ACPI_NAMESPACE_NODE     *Node;
931    ACPI_STATUS             Status;
932
933
934    /* Parameter validation */
935
936    if (!ObjHandle  ||
937        !Handler    ||
938        !Data)
939    {
940        return (AE_BAD_PARAMETER);
941    }
942
943    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
944    if (ACPI_FAILURE (Status))
945    {
946        return (Status);
947    }
948
949    /* Convert and validate the handle */
950
951    Node = AcpiNsValidateHandle (ObjHandle);
952    if (!Node)
953    {
954        Status = AE_BAD_PARAMETER;
955        goto UnlockAndExit;
956    }
957
958    Status = AcpiNsAttachData (Node, Handler, Data);
959
960UnlockAndExit:
961    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
962    return (Status);
963}
964
965ACPI_EXPORT_SYMBOL (AcpiAttachData)
966
967
968/*******************************************************************************
969 *
970 * FUNCTION:    AcpiDetachData
971 *
972 * PARAMETERS:  ObjHandle           - Namespace node handle
973 *              Handler             - Handler used in call to AcpiAttachData
974 *
975 * RETURN:      Status
976 *
977 * DESCRIPTION: Remove data that was previously attached to a node.
978 *
979 ******************************************************************************/
980
981ACPI_STATUS
982AcpiDetachData (
983    ACPI_HANDLE             ObjHandle,
984    ACPI_OBJECT_HANDLER     Handler)
985{
986    ACPI_NAMESPACE_NODE     *Node;
987    ACPI_STATUS             Status;
988
989
990    /* Parameter validation */
991
992    if (!ObjHandle  ||
993        !Handler)
994    {
995        return (AE_BAD_PARAMETER);
996    }
997
998    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
999    if (ACPI_FAILURE (Status))
1000    {
1001        return (Status);
1002    }
1003
1004    /* Convert and validate the handle */
1005
1006    Node = AcpiNsValidateHandle (ObjHandle);
1007    if (!Node)
1008    {
1009        Status = AE_BAD_PARAMETER;
1010        goto UnlockAndExit;
1011    }
1012
1013    Status = AcpiNsDetachData (Node, Handler);
1014
1015UnlockAndExit:
1016    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1017    return (Status);
1018}
1019
1020ACPI_EXPORT_SYMBOL (AcpiDetachData)
1021
1022
1023/*******************************************************************************
1024 *
1025 * FUNCTION:    AcpiGetData
1026 *
1027 * PARAMETERS:  ObjHandle           - Namespace node
1028 *              Handler             - Handler used in call to AttachData
1029 *              Data                - Where the data is returned
1030 *
1031 * RETURN:      Status
1032 *
1033 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
1034 *
1035 ******************************************************************************/
1036
1037ACPI_STATUS
1038AcpiGetData (
1039    ACPI_HANDLE             ObjHandle,
1040    ACPI_OBJECT_HANDLER     Handler,
1041    void                    **Data)
1042{
1043    ACPI_NAMESPACE_NODE     *Node;
1044    ACPI_STATUS             Status;
1045
1046
1047    /* Parameter validation */
1048
1049    if (!ObjHandle  ||
1050        !Handler    ||
1051        !Data)
1052    {
1053        return (AE_BAD_PARAMETER);
1054    }
1055
1056    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1057    if (ACPI_FAILURE (Status))
1058    {
1059        return (Status);
1060    }
1061
1062    /* Convert and validate the handle */
1063
1064    Node = AcpiNsValidateHandle (ObjHandle);
1065    if (!Node)
1066    {
1067        Status = AE_BAD_PARAMETER;
1068        goto UnlockAndExit;
1069    }
1070
1071    Status = AcpiNsGetAttachedData (Node, Handler, Data);
1072
1073UnlockAndExit:
1074    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1075    return (Status);
1076}
1077
1078ACPI_EXPORT_SYMBOL (AcpiGetData)
1079