Merge from vendor branch CVS:
[dragonfly.git] / sys / contrib / dev / acpica / nseval.c
1 /*******************************************************************************
2  *
3  * Module Name: nseval - Object evaluation interfaces -- includes control
4  *                       method lookup and execution.
5  *              $Revision: 121 $
6  *
7  ******************************************************************************/
8
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
14  * All rights reserved.
15  *
16  * 2. License
17  *
18  * 2.1. This is your license from Intel Corp. under its intellectual property
19  * rights.  You may have additional license terms from the party that provided
20  * you this software, covering your right to use that party's intellectual
21  * property rights.
22  *
23  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24  * copy of the source code appearing in this file ("Covered Code") an
25  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26  * base code distributed originally by Intel ("Original Intel Code") to copy,
27  * make derivatives, distribute, use and display any portion of the Covered
28  * Code in any form, with the right to sublicense such rights; and
29  *
30  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31  * license (with the right to sublicense), under only those claims of Intel
32  * patents that are infringed by the Original Intel Code, to make, use, sell,
33  * offer to sell, and import the Covered Code and derivative works thereof
34  * solely to the minimum extent necessary to exercise the above copyright
35  * license, and in no event shall the patent license extend to any additions
36  * to or modifications of the Original Intel Code.  No other license or right
37  * is granted directly or by implication, estoppel or otherwise;
38  *
39  * The above copyright and patent license is granted only if the following
40  * conditions are met:
41  *
42  * 3. Conditions
43  *
44  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45  * Redistribution of source code of any substantial portion of the Covered
46  * Code or modification with rights to further distribute source must include
47  * the above Copyright Notice, the above License, this list of Conditions,
48  * and the following Disclaimer and Export Compliance provision.  In addition,
49  * Licensee must cause all Covered Code to which Licensee contributes to
50  * contain a file documenting the changes Licensee made to create that Covered
51  * Code and the date of any change.  Licensee must include in that file the
52  * documentation of any changes made by any predecessor Licensee.  Licensee
53  * must include a prominent statement that the modification is derived,
54  * directly or indirectly, from Original Intel Code.
55  *
56  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57  * Redistribution of source code of any substantial portion of the Covered
58  * Code or modification without rights to further distribute source must
59  * include the following Disclaimer and Export Compliance provision in the
60  * documentation and/or other materials provided with distribution.  In
61  * addition, Licensee may not authorize further sublicense of source of any
62  * portion of the Covered Code, and must include terms to the effect that the
63  * license from Licensee to its licensee is limited to the intellectual
64  * property embodied in the software Licensee provides to its licensee, and
65  * not to intellectual property embodied in modifications its licensee may
66  * make.
67
68  *
69  * 3.3. Redistribution of Executable. Redistribution in executable form of any
70  * substantial portion of the Covered Code or modification must reproduce the
71  * above Copyright Notice, and the following Disclaimer and Export Compliance
72  * provision in the documentation and/or other materials provided with the
73  * distribution.
74  *
75  * 3.4. Intel retains all right, title, and interest in and to the Original
76  * Intel Code.
77  *
78  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
79  * Intel shall be used in advertising or otherwise to promote the sale, use or
80  * other dealings in products derived from or relating to the Covered Code
81  * without prior written authorization from Intel.
82  *
83  * 4. Disclaimer and Export Compliance
84  *
85  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
86  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
87  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
88  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
89  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
90  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91  * PARTICULAR PURPOSE.
92  *
93  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
99  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100  * LIMITED REMEDY.
101  *
102  * 4.3. Licensee shall not export, either directly or indirectly, any of this
103  * software or system incorporating such software without first obtaining any
104  * required license or other approval from the U. S. Department of Commerce or
105  * any other agency or department of the United States Government.  In the
106  * event Licensee exports any such software from the United States or
107  * re-exports any such software from a foreign destination, Licensee shall
108  * ensure that the distribution and export/re-export of the software is in
109  * compliance with all laws, regulations, orders, or other restrictions of the
110  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111  * any of its subsidiaries will export/re-export any technical data, process,
112  * software, or service, directly or indirectly, to any country for which the
113  * United States government or any agency thereof requires an export license,
114  * other governmental approval, or letter of assurance, without first obtaining
115  * such license, approval or letter.
116  *
117  *****************************************************************************/
118 /* $DragonFly: src/sys/contrib/dev/acpica/Attic/nseval.c,v 1.1 2003/09/24 03:32:16 drhodus Exp $                                                               */
119
120 #define __NSEVAL_C__
121
122 #include "acpi.h"
123 #include "acparser.h"
124 #include "acinterp.h"
125 #include "acnamesp.h"
126
127
128 #define _COMPONENT          ACPI_NAMESPACE
129         ACPI_MODULE_NAME    ("nseval")
130
131
132 /*******************************************************************************
133  *
134  * FUNCTION:    AcpiNsEvaluateRelative
135  *
136  * PARAMETERS:  Handle              - The relative containing object
137  *              Pathname            - Name of method to execute, If NULL, the
138  *                                    handle is the object to execute
139  *              Params              - List of parameters to pass to the method,
140  *                                    terminated by NULL.  Params itself may be
141  *                                    NULL if no parameters are being passed.
142  *              ReturnObject        - Where to put method's return value (if
143  *                                    any).  If NULL, no value is returned.
144  *
145  * RETURN:      Status
146  *
147  * DESCRIPTION: Find and execute the requested method using the handle as a
148  *              scope
149  *
150  * MUTEX:       Locks Namespace
151  *
152  ******************************************************************************/
153
154 ACPI_STATUS
155 AcpiNsEvaluateRelative (
156     ACPI_NAMESPACE_NODE     *Handle,
157     char                    *Pathname,
158     ACPI_OPERAND_OBJECT     **Params,
159     ACPI_OPERAND_OBJECT     **ReturnObject)
160 {
161     ACPI_NAMESPACE_NODE     *PrefixNode;
162     ACPI_STATUS             Status;
163     ACPI_NAMESPACE_NODE     *Node = NULL;
164     char                    *InternalPath = NULL;
165     ACPI_GENERIC_STATE      ScopeInfo;
166
167
168     ACPI_FUNCTION_TRACE ("NsEvaluateRelative");
169
170
171     /*
172      * Must have a valid object handle
173      */
174     if (!Handle)
175     {
176         return_ACPI_STATUS (AE_BAD_PARAMETER);
177     }
178
179     /* Build an internal name string for the method */
180
181     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
182     if (ACPI_FAILURE (Status))
183     {
184         return_ACPI_STATUS (Status);
185     }
186
187     /* Get the prefix handle and Node */
188
189     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
190     if (ACPI_FAILURE (Status))
191     {
192         return_ACPI_STATUS (Status);
193     }
194
195     PrefixNode = AcpiNsMapHandleToNode (Handle);
196     if (!PrefixNode)
197     {
198         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
199         Status = AE_BAD_PARAMETER;
200         goto Cleanup;
201     }
202
203     /* Lookup the name in the namespace */
204
205     ScopeInfo.Scope.Node = PrefixNode;
206     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
207                             ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
208                             &Node);
209
210     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
211
212     if (ACPI_FAILURE (Status))
213     {
214         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
215             Pathname, AcpiFormatException (Status)));
216         goto Cleanup;
217     }
218
219     /*
220      * Now that we have a handle to the object, we can attempt
221      * to evaluate it.
222      */
223     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
224         Pathname, Node, AcpiNsGetAttachedObject (Node)));
225
226     Status = AcpiNsEvaluateByHandle (Node, Params, ReturnObject);
227
228     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
229         Pathname));
230
231 Cleanup:
232
233     ACPI_MEM_FREE (InternalPath);
234     return_ACPI_STATUS (Status);
235 }
236
237
238 /*******************************************************************************
239  *
240  * FUNCTION:    AcpiNsEvaluateByName
241  *
242  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
243  *              ReturnObject        - Where to put method's return value (if
244  *                                    any).  If NULL, no value is returned.
245  *              Params              - List of parameters to pass to the method,
246  *                                    terminated by NULL.  Params itself may be
247  *                                    NULL if no parameters are being passed.
248  *
249  * RETURN:      Status
250  *
251  * DESCRIPTION: Find and execute the requested method passing the given
252  *              parameters
253  *
254  * MUTEX:       Locks Namespace
255  *
256  ******************************************************************************/
257
258 ACPI_STATUS
259 AcpiNsEvaluateByName (
260     char                    *Pathname,
261     ACPI_OPERAND_OBJECT     **Params,
262     ACPI_OPERAND_OBJECT     **ReturnObject)
263 {
264     ACPI_STATUS             Status;
265     ACPI_NAMESPACE_NODE     *Node = NULL;
266     char                    *InternalPath = NULL;
267
268
269     ACPI_FUNCTION_TRACE ("NsEvaluateByName");
270
271
272     /* Build an internal name string for the method */
273
274     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
275     if (ACPI_FAILURE (Status))
276     {
277         return_ACPI_STATUS (Status);
278     }
279
280     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
281     if (ACPI_FAILURE (Status))
282     {
283         return_ACPI_STATUS (Status);
284     }
285
286     /* Lookup the name in the namespace */
287
288     Status = AcpiNsLookup (NULL, InternalPath, ACPI_TYPE_ANY,
289                             ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
290                             &Node);
291
292     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
293
294     if (ACPI_FAILURE (Status))
295     {
296         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object at [%s] was not found, status=%.4X\n",
297             Pathname, Status));
298         goto Cleanup;
299     }
300
301     /*
302      * Now that we have a handle to the object, we can attempt
303      * to evaluate it.
304      */
305     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
306         Pathname, Node, AcpiNsGetAttachedObject (Node)));
307
308     Status = AcpiNsEvaluateByHandle (Node, Params, ReturnObject);
309
310     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
311         Pathname));
312
313
314 Cleanup:
315
316     /* Cleanup */
317
318     if (InternalPath)
319     {
320         ACPI_MEM_FREE (InternalPath);
321     }
322
323     return_ACPI_STATUS (Status);
324 }
325
326
327 /*******************************************************************************
328  *
329  * FUNCTION:    AcpiNsEvaluateByHandle
330  *
331  * PARAMETERS:  Handle              - Method Node to execute
332  *              Params              - List of parameters to pass to the method,
333  *                                    terminated by NULL.  Params itself may be
334  *                                    NULL if no parameters are being passed.
335  *              ReturnObject        - Where to put method's return value (if
336  *                                    any).  If NULL, no value is returned.
337  *
338  * RETURN:      Status
339  *
340  * DESCRIPTION: Execute the requested method passing the given parameters
341  *
342  * MUTEX:       Locks Namespace
343  *
344  ******************************************************************************/
345
346 ACPI_STATUS
347 AcpiNsEvaluateByHandle (
348     ACPI_NAMESPACE_NODE     *Handle,
349     ACPI_OPERAND_OBJECT     **Params,
350     ACPI_OPERAND_OBJECT     **ReturnObject)
351 {
352     ACPI_NAMESPACE_NODE     *Node;
353     ACPI_STATUS             Status;
354     ACPI_OPERAND_OBJECT     *LocalReturnObject;
355
356
357     ACPI_FUNCTION_TRACE ("NsEvaluateByHandle");
358
359
360     /* Check if namespace has been initialized */
361
362     if (!AcpiGbl_RootNode)
363     {
364         return_ACPI_STATUS (AE_NO_NAMESPACE);
365     }
366
367     /* Parameter Validation */
368
369     if (!Handle)
370     {
371         return_ACPI_STATUS (AE_BAD_PARAMETER);
372     }
373
374     if (ReturnObject)
375     {
376         /* Initialize the return value to an invalid object */
377
378         *ReturnObject = NULL;
379     }
380
381     /* Get the prefix handle and Node */
382
383     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
384     if (ACPI_FAILURE (Status))
385     {
386         return_ACPI_STATUS (Status);
387     }
388
389     Node = AcpiNsMapHandleToNode (Handle);
390     if (!Node)
391     {
392         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
393         return_ACPI_STATUS (AE_BAD_PARAMETER);
394     }
395
396     /*
397      * Two major cases here:
398      * 1) The object is an actual control method -- execute it.
399      * 2) The object is not a method -- just return it's current
400      *      value
401      *
402      * In both cases, the namespace is unlocked by the
403      *  AcpiNs* procedure
404      */
405     if (AcpiNsGetType (Node) == ACPI_TYPE_METHOD)
406     {
407         /*
408          * Case 1) We have an actual control method to execute
409          */
410         Status = AcpiNsExecuteControlMethod (Node, Params,
411                                             &LocalReturnObject);
412     }
413     else
414     {
415         /*
416          * Case 2) Object is NOT a method, just return its
417          * current value
418          */
419         Status = AcpiNsGetObjectValue (Node, &LocalReturnObject);
420     }
421
422     /*
423      * Check if there is a return value on the stack that must
424      * be dealt with
425      */
426     if (Status == AE_CTRL_RETURN_VALUE)
427     {
428         /*
429          * If the Method returned a value and the caller
430          * provided a place to store a returned value, Copy
431          * the returned value to the object descriptor provided
432          * by the caller.
433          */
434         if (ReturnObject)
435         {
436             /*
437              * Valid return object, copy the pointer to
438              * the returned object
439              */
440             *ReturnObject = LocalReturnObject;
441         }
442
443         /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
444
445         Status = AE_OK;
446     }
447
448     /*
449      * Namespace was unlocked by the handling AcpiNs* function,
450      * so we just return
451      */
452     return_ACPI_STATUS (Status);
453 }
454
455
456 /*******************************************************************************
457  *
458  * FUNCTION:    AcpiNsExecuteControlMethod
459  *
460  * PARAMETERS:  MethodNode          - The method to execute
461  *              Params              - List of parameters to pass to the method,
462  *                                    terminated by NULL.  Params itself may be
463  *                                    NULL if no parameters are being passed.
464  *              ReturnObjDesc       - List of result objects to be returned
465  *                                    from the method.
466  *
467  * RETURN:      Status
468  *
469  * DESCRIPTION: Execute the requested method passing the given parameters
470  *
471  * MUTEX:       Assumes namespace is locked
472  *
473  ******************************************************************************/
474
475 ACPI_STATUS
476 AcpiNsExecuteControlMethod (
477     ACPI_NAMESPACE_NODE     *MethodNode,
478     ACPI_OPERAND_OBJECT     **Params,
479     ACPI_OPERAND_OBJECT     **ReturnObjDesc)
480 {
481     ACPI_STATUS             Status;
482     ACPI_OPERAND_OBJECT     *ObjDesc;
483
484
485     ACPI_FUNCTION_TRACE ("NsExecuteControlMethod");
486
487
488     /* Verify that there is a method associated with this object */
489
490     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
491     if (!ObjDesc)
492     {
493         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
494
495         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
496         return_ACPI_STATUS (AE_NULL_OBJECT);
497     }
498
499     ACPI_DUMP_PATHNAME (MethodNode, "Execute Method:",
500         ACPI_LV_INFO, _COMPONENT);
501
502     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
503         ObjDesc->Method.AmlStart + 1, ObjDesc->Method.AmlLength - 1));
504
505     /*
506      * Unlock the namespace before execution.  This allows namespace access
507      * via the external Acpi* interfaces while a method is being executed.
508      * However, any namespace deletion must acquire both the namespace and
509      * interpreter locks to ensure that no thread is using the portion of the
510      * namespace that is being deleted.
511      */
512     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
513     if (ACPI_FAILURE (Status))
514     {
515         return_ACPI_STATUS (Status);
516     }
517
518     /*
519      * Execute the method via the interpreter.  The interpreter is locked
520      * here before calling into the AML parser
521      */
522     Status = AcpiExEnterInterpreter ();
523     if (ACPI_FAILURE (Status))
524     {
525         return_ACPI_STATUS (Status);
526     }
527
528     Status = AcpiPsxExecute (MethodNode, Params, ReturnObjDesc);
529     AcpiExExitInterpreter ();
530
531     return_ACPI_STATUS (Status);
532 }
533
534
535 /*******************************************************************************
536  *
537  * FUNCTION:    AcpiNsGetObjectValue
538  *
539  * PARAMETERS:  Node                - The object
540  *              ReturnObjDesc       - Where the objects value is returned
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: Return the current value of the object
545  *
546  * MUTEX:       Assumes namespace is locked, leaves namespace unlocked
547  *
548  ******************************************************************************/
549
550 ACPI_STATUS
551 AcpiNsGetObjectValue (
552     ACPI_NAMESPACE_NODE     *Node,
553     ACPI_OPERAND_OBJECT     **ReturnObjDesc)
554 {
555     ACPI_STATUS             Status = AE_OK;
556     ACPI_NAMESPACE_NODE     *ResolvedNode = Node;
557
558
559     ACPI_FUNCTION_TRACE ("NsGetObjectValue");
560
561
562     /*
563      * Objects require additional resolution steps (e.g., the
564      * Node may be a field that must be read, etc.) -- we can't just grab
565      * the object out of the node.
566      */
567
568     /*
569      * Use ResolveNodeToValue() to get the associated value.  This call
570      * always deletes ObjDesc (allocated above).
571      *
572      * NOTE: we can get away with passing in NULL for a walk state
573      * because ObjDesc is guaranteed to not be a reference to either
574      * a method local or a method argument (because this interface can only be
575      * called from the AcpiEvaluate external interface, never called from
576      * a running control method.)
577      *
578      * Even though we do not directly invoke the interpreter
579      * for this, we must enter it because we could access an opregion.
580      * The opregion access code assumes that the interpreter
581      * is locked.
582      *
583      * We must release the namespace lock before entering the
584      * intepreter.
585      */
586     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
587     if (ACPI_FAILURE (Status))
588     {
589         return_ACPI_STATUS (Status);
590     }
591
592     Status = AcpiExEnterInterpreter ();
593     if (ACPI_SUCCESS (Status))
594     {
595         Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL);
596         /*
597          * If AcpiExResolveNodeToValue() succeeded, the return value was
598          * placed in ResolvedNode.
599          */
600         AcpiExExitInterpreter ();
601
602         if (ACPI_SUCCESS (Status))
603         {
604             Status = AE_CTRL_RETURN_VALUE;
605             *ReturnObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ResolvedNode);
606             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
607                 *ReturnObjDesc, AcpiUtGetObjectTypeName (*ReturnObjDesc)));
608         }
609     }
610
611     /* Namespace is unlocked */
612
613     return_ACPI_STATUS (Status);
614 }
615