nsxfeval.c revision 202771
150120Swpaul/*******************************************************************************
250120Swpaul *
350120Swpaul * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
450120Swpaul *                         ACPI Object evaluation interfaces
550120Swpaul *
650120Swpaul ******************************************************************************/
750120Swpaul
850120Swpaul/******************************************************************************
950120Swpaul *
1050120Swpaul * 1. Copyright Notice
1150120Swpaul *
1250120Swpaul * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
1350120Swpaul * All rights reserved.
1450120Swpaul *
1550120Swpaul * 2. License
1650120Swpaul *
1750120Swpaul * 2.1. This is your license from Intel Corp. under its intellectual property
1850120Swpaul * rights.  You may have additional license terms from the party that provided
1950120Swpaul * you this software, covering your right to use that party's intellectual
2050120Swpaul * property rights.
2150120Swpaul *
2250120Swpaul * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2350120Swpaul * copy of the source code appearing in this file ("Covered Code") an
2450120Swpaul * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2550120Swpaul * base code distributed originally by Intel ("Original Intel Code") to copy,
2650120Swpaul * make derivatives, distribute, use and display any portion of the Covered
2750120Swpaul * Code in any form, with the right to sublicense such rights; and
2850120Swpaul *
2950120Swpaul * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3050120Swpaul * license (with the right to sublicense), under only those claims of Intel
3150120Swpaul * patents that are infringed by the Original Intel Code, to make, use, sell,
3250477Speter * offer to sell, and import the Covered Code and derivative works thereof
3350120Swpaul * solely to the minimum extent necessary to exercise the above copyright
3450120Swpaul * license, and in no event shall the patent license extend to any additions
3550120Swpaul * to or modifications of the Original Intel Code.  No other license or right
3650120Swpaul * is granted directly or by implication, estoppel or otherwise;
3750120Swpaul *
3850120Swpaul * The above copyright and patent license is granted only if the following
3950120Swpaul * conditions are met:
4050120Swpaul *
41221407Smarius * 3. Conditions
4250120Swpaul *
4350120Swpaul * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4450120Swpaul * Redistribution of source code of any substantial portion of the Covered
4550120Swpaul * Code or modification with rights to further distribute source must include
4650120Swpaul * the above Copyright Notice, the above License, this list of Conditions,
4750120Swpaul * and the following Disclaimer and Export Compliance provision.  In addition,
4850120Swpaul * Licensee must cause all Covered Code to which Licensee contributes to
4992739Salfred * contain a file documenting the changes Licensee made to create that Covered
5092739Salfred * Code and the date of any change.  Licensee must include in that file the
5192739Salfred * documentation of any changes made by any predecessor Licensee.  Licensee
5250120Swpaul * must include a prominent statement that the modification is derived,
5350120Swpaul * directly or indirectly, from Original Intel Code.
5450120Swpaul *
5550120Swpaul * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5650120Swpaul * Redistribution of source code of any substantial portion of the Covered
5750120Swpaul * Code or modification without rights to further distribute source must
5850120Swpaul * include the following Disclaimer and Export Compliance provision in the
5950120Swpaul * documentation and/or other materials provided with distribution.  In
6050120Swpaul * addition, Licensee may not authorize further sublicense of source of any
6150120Swpaul * portion of the Covered Code, and must include terms to the effect that the
6250120Swpaul * license from Licensee to its licensee is limited to the intellectual
6350120Swpaul * property embodied in the software Licensee provides to its licensee, and
6450120Swpaul * not to intellectual property embodied in modifications its licensee may
6550120Swpaul * make.
6650120Swpaul *
6760938Sjake * 3.3. Redistribution of Executable. Redistribution in executable form of any
68221407Smarius * substantial portion of the Covered Code or modification must reproduce the
6950120Swpaul * above Copyright Notice, and the following Disclaimer and Export Compliance
7050120Swpaul * provision in the documentation and/or other materials provided with the
7150120Swpaul * distribution.
7250120Swpaul *
73221407Smarius * 3.4. Intel retains all right, title, and interest in and to the Original
74221407Smarius * Intel Code.
7550120Swpaul *
7650120Swpaul * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7750120Swpaul * Intel shall be used in advertising or otherwise to promote the sale, use or
7850120Swpaul * other dealings in products derived from or relating to the Covered Code
7950120Swpaul * without prior written authorization from Intel.
8050120Swpaul *
8150120Swpaul * 4. Disclaimer and Export Compliance
8250120Swpaul *
8350120Swpaul * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8450120Swpaul * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8550120Swpaul * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86221407Smarius * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8750120Swpaul * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88221407Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89221407Smarius * PARTICULAR PURPOSE.
90221407Smarius *
91221407Smarius * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92221407Smarius * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9350120Swpaul * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9450120Swpaul * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9550120Swpaul * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9650120Swpaul * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9750120Swpaul * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9850120Swpaul * LIMITED REMEDY.
9950120Swpaul *
10050120Swpaul * 4.3. Licensee shall not export, either directly or indirectly, any of this
10150120Swpaul * software or system incorporating such software without first obtaining any
10250120Swpaul * required license or other approval from the U. S. Department of Commerce or
10350120Swpaul * any other agency or department of the United States Government.  In the
10450120Swpaul * event Licensee exports any such software from the United States or
10550120Swpaul * re-exports any such software from a foreign destination, Licensee shall
10650120Swpaul * ensure that the distribution and export/re-export of the software is in
10750120Swpaul * compliance with all laws, regulations, orders, or other restrictions of the
108213878Smarius * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10960938Sjake * any of its subsidiaries will export/re-export any technical data, process,
11050120Swpaul * software, or service, directly or indirectly, to any country for which the
111221407Smarius * United States government or any agency thereof requires an export license,
112221407Smarius * other governmental approval, or letter of assurance, without first obtaining
113221407Smarius * such license, approval or letter.
114221407Smarius *
115221407Smarius *****************************************************************************/
116221407Smarius
117221407Smarius
11850120Swpaul#define __NSXFEVAL_C__
119221407Smarius
120221407Smarius#include <contrib/dev/acpica/include/acpi.h>
121221407Smarius#include <contrib/dev/acpica/include/accommon.h>
12250120Swpaul#include <contrib/dev/acpica/include/acnamesp.h>
12350120Swpaul#include <contrib/dev/acpica/include/acinterp.h>
124221407Smarius
125221407Smarius
126221407Smarius#define _COMPONENT          ACPI_NAMESPACE
127221407Smarius        ACPI_MODULE_NAME    ("nsxfeval")
128221407Smarius
129221407Smarius/* Local prototypes */
130221407Smarius
13150120Swpaulstatic void
13250120SwpaulAcpiNsResolveReferences (
13350120Swpaul    ACPI_EVALUATE_INFO      *Info);
13450120Swpaul
135213878Smarius
136213878Smarius/*******************************************************************************
137221407Smarius *
138213878Smarius * FUNCTION:    AcpiEvaluateObjectTyped
139221407Smarius *
140215297Smarius * PARAMETERS:  Handle              - Object handle (optional)
141213878Smarius *              Pathname            - Object pathname (optional)
142213878Smarius *              ExternalParams      - List of parameters to pass to method,
143213878Smarius *                                    terminated by NULL.  May be NULL
144213878Smarius *                                    if no parameters are being passed.
145213878Smarius *              ReturnBuffer        - Where to put method's return value (if
146213878Smarius *                                    any).  If NULL, no value is returned.
147213878Smarius *              ReturnType          - Expected type of return object
148215297Smarius *
149220938Smarius * RETURN:      Status
150213878Smarius *
151213878Smarius * DESCRIPTION: Find and evaluate the given object, passing the given
152213878Smarius *              parameters if necessary.  One of "Handle" or "Pathname" must
153213878Smarius *              be valid (non-null)
154213878Smarius *
155213878Smarius ******************************************************************************/
15650120Swpaul
157158648SolegACPI_STATUS
158158648SolegAcpiEvaluateObjectTyped (
159158648Soleg    ACPI_HANDLE             Handle,
160158648Soleg    ACPI_STRING             Pathname,
16195707Sphk    ACPI_OBJECT_LIST        *ExternalParams,
16295707Sphk    ACPI_BUFFER             *ReturnBuffer,
16350120Swpaul    ACPI_OBJECT_TYPE        ReturnType)
164213878Smarius{
165213878Smarius    ACPI_STATUS             Status;
166214605Smarius    BOOLEAN                 MustFree = FALSE;
167213878Smarius
168213878Smarius
169213878Smarius    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
170213878Smarius
171213878Smarius
17250120Swpaul    /* Return buffer must be valid */
17350120Swpaul
17450120Swpaul    if (!ReturnBuffer)
17550120Swpaul    {
176221407Smarius        return_ACPI_STATUS (AE_BAD_PARAMETER);
177221407Smarius    }
178221407Smarius
179221407Smarius    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
180221407Smarius    {
18150120Swpaul        MustFree = TRUE;
18250120Swpaul    }
18350120Swpaul
18495707Sphk    /* Evaluate the object */
18595724Sphk
18695724Sphk    Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
18795724Sphk    if (ACPI_FAILURE (Status))
188221407Smarius    {
189221407Smarius        return_ACPI_STATUS (Status);
19095724Sphk    }
19195724Sphk
192150755Simp    /* Type ANY means "don't care" */
193150755Simp
194150755Simp    if (ReturnType == ACPI_TYPE_ANY)
19595724Sphk    {
19695724Sphk        return_ACPI_STATUS (AE_OK);
19795707Sphk    }
19895707Sphk
19995707Sphk    if (ReturnBuffer->Length == 0)
200221407Smarius    {
201221407Smarius        /* Error because caller specifically asked for a return value */
202221407Smarius
20395707Sphk        ACPI_ERROR ((AE_INFO, "No return value"));
20495707Sphk        return_ACPI_STATUS (AE_NULL_OBJECT);
20595707Sphk    }
20695707Sphk
20795707Sphk    /* Examine the object type returned from EvaluateObject */
20895707Sphk
20995707Sphk    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
21095707Sphk    {
21195707Sphk        return_ACPI_STATUS (AE_OK);
21295707Sphk    }
21395707Sphk
21495707Sphk    /* Return object type does not match requested type */
21595707Sphk
21695707Sphk    ACPI_ERROR ((AE_INFO,
21755205Speter        "Incorrect return type [%s] requested [%s]",
21850120Swpaul        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
21950120Swpaul        AcpiUtGetTypeName (ReturnType)));
22050120Swpaul
22150120Swpaul    if (MustFree)
22250120Swpaul    {
22350120Swpaul        /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
22450120Swpaul
225221407Smarius        AcpiOsFree (ReturnBuffer->Pointer);
226221407Smarius        ReturnBuffer->Pointer = NULL;
227221407Smarius    }
228221407Smarius
229221407Smarius    ReturnBuffer->Length = 0;
230221407Smarius    return_ACPI_STATUS (AE_TYPE);
231221407Smarius}
232221407Smarius
233221407SmariusACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
234213878Smarius
235213878Smarius
236213878Smarius/*******************************************************************************
237213878Smarius *
238213878Smarius * FUNCTION:    AcpiEvaluateObject
239213878Smarius *
240213878Smarius * PARAMETERS:  Handle              - Object handle (optional)
241213878Smarius *              Pathname            - Object pathname (optional)
242213878Smarius *              ExternalParams      - List of parameters to pass to method,
243213878Smarius *                                    terminated by NULL.  May be NULL
244221407Smarius *                                    if no parameters are being passed.
245213878Smarius *              ReturnBuffer        - Where to put method's return value (if
24650120Swpaul *                                    any).  If NULL, no value is returned.
24750120Swpaul *
24850120Swpaul * RETURN:      Status
249213878Smarius *
250213878Smarius * DESCRIPTION: Find and evaluate the given object, passing the given
25195722Sphk *              parameters if necessary.  One of "Handle" or "Pathname" must
25292739Salfred *              be valid (non-null)
25392739Salfred *
25492739Salfred ******************************************************************************/
25595718Sphk
25650120SwpaulACPI_STATUS
25796026SphkAcpiEvaluateObject (
25895722Sphk    ACPI_HANDLE             Handle,
25995722Sphk    ACPI_STRING             Pathname,
260215297Smarius    ACPI_OBJECT_LIST        *ExternalParams,
26192739Salfred    ACPI_BUFFER             *ReturnBuffer)
26295707Sphk{
26392739Salfred    ACPI_STATUS             Status;
26492739Salfred    ACPI_EVALUATE_INFO      *Info;
26550120Swpaul    ACPI_SIZE               BufferSpaceNeeded;
266150756Simp    UINT32                  i;
267150756Simp
268150756Simp
269150756Simp    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
270164827Smarius
271221407Smarius
272221407Smarius    /* Allocate and initialize the evaluation information block */
27395724Sphk
27492739Salfred    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
275221407Smarius    if (!Info)
276221407Smarius    {
277221407Smarius        return_ACPI_STATUS (AE_NO_MEMORY);
278221407Smarius    }
279221407Smarius
280221407Smarius    Info->Pathname = Pathname;
28155205Speter
28250120Swpaul    /* Convert and validate the device handle */
28350120Swpaul
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