Merge branch 'vendor/OPENSSL'
[dragonfly.git] / sys / contrib / dev / acpica / source / components / namespace / nseval.c
1 /*******************************************************************************
2  *
3  * Module Name: nseval - Object evaluation, includes control method execution
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #define __NSEVAL_C__
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acparser.h"
49 #include "acinterp.h"
50 #include "acnamesp.h"
51
52
53 #define _COMPONENT          ACPI_NAMESPACE
54         ACPI_MODULE_NAME    ("nseval")
55
56 /* Local prototypes */
57
58 static void
59 AcpiNsExecModuleCode (
60     ACPI_OPERAND_OBJECT     *MethodObj,
61     ACPI_EVALUATE_INFO      *Info);
62
63
64 /*******************************************************************************
65  *
66  * FUNCTION:    AcpiNsEvaluate
67  *
68  * PARAMETERS:  Info            - Evaluation info block, contains:
69  *                  PrefixNode      - Prefix or Method/Object Node to execute
70  *                  RelativePath    - Name of method to execute, If NULL, the
71  *                                    Node is the object to execute
72  *                  Parameters      - List of parameters to pass to the method,
73  *                                    terminated by NULL. Params itself may be
74  *                                    NULL if no parameters are being passed.
75  *                  ReturnObject    - Where to put method's return value (if
76  *                                    any). If NULL, no value is returned.
77  *                  ParameterType   - Type of Parameter list
78  *                  ReturnObject    - Where to put method's return value (if
79  *                                    any). If NULL, no value is returned.
80  *                  Flags           - ACPI_IGNORE_RETURN_VALUE to delete return
81  *
82  * RETURN:      Status
83  *
84  * DESCRIPTION: Execute a control method or return the current value of an
85  *              ACPI namespace object.
86  *
87  * MUTEX:       Locks interpreter
88  *
89  ******************************************************************************/
90
91 ACPI_STATUS
92 AcpiNsEvaluate (
93     ACPI_EVALUATE_INFO      *Info)
94 {
95     ACPI_STATUS             Status;
96
97
98     ACPI_FUNCTION_TRACE (NsEvaluate);
99
100
101     if (!Info)
102     {
103         return_ACPI_STATUS (AE_BAD_PARAMETER);
104     }
105
106     if (!Info->Node)
107     {
108         /*
109          * Get the actual namespace node for the target object if we
110          * need to. Handles these cases:
111          *
112          * 1) Null node, valid pathname from root (absolute path)
113          * 2) Node and valid pathname (path relative to Node)
114          * 3) Node, Null pathname
115          */
116         Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname,
117             ACPI_NS_NO_UPSEARCH, &Info->Node);
118         if (ACPI_FAILURE (Status))
119         {
120             return_ACPI_STATUS (Status);
121         }
122     }
123
124     /*
125      * For a method alias, we must grab the actual method node so that
126      * proper scoping context will be established before execution.
127      */
128     if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
129     {
130         Info->Node = ACPI_CAST_PTR (
131             ACPI_NAMESPACE_NODE, Info->Node->Object);
132     }
133
134     /* Complete the info block initialization */
135
136     Info->ReturnObject = NULL;
137     Info->NodeFlags = Info->Node->Flags;
138     Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node);
139
140     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
141         Info->RelativePathname, Info->Node,
142         AcpiNsGetAttachedObject (Info->Node)));
143
144     /* Get info if we have a predefined name (_HID, etc.) */
145
146     Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii);
147
148     /* Get the full pathname to the object, for use in warning messages */
149
150     Info->FullPathname = AcpiNsGetExternalPathname (Info->Node);
151     if (!Info->FullPathname)
152     {
153         return_ACPI_STATUS (AE_NO_MEMORY);
154     }
155
156     /* Count the number of arguments being passed in */
157
158     Info->ParamCount = 0;
159     if (Info->Parameters)
160     {
161         while (Info->Parameters[Info->ParamCount])
162         {
163             Info->ParamCount++;
164         }
165
166         /* Warn on impossible argument count */
167
168         if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
169         {
170             ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS,
171                 "Excess arguments (%u) - using only %u",
172                 Info->ParamCount, ACPI_METHOD_NUM_ARGS));
173
174             Info->ParamCount = ACPI_METHOD_NUM_ARGS;
175         }
176     }
177
178     /*
179      * For predefined names: Check that the declared argument count
180      * matches the ACPI spec -- otherwise this is a BIOS error.
181      */
182     AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node,
183         Info->Predefined);
184
185     /*
186      * For all names: Check that the incoming argument count for
187      * this method/object matches the actual ASL/AML definition.
188      */
189     AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node,
190         Info->ParamCount, Info->Predefined);
191
192     /* For predefined names: Typecheck all incoming arguments */
193
194     AcpiNsCheckArgumentTypes (Info);
195
196     /*
197      * Three major evaluation cases:
198      *
199      * 1) Object types that cannot be evaluated by definition
200      * 2) The object is a control method -- execute it
201      * 3) The object is not a method -- just return it's current value
202      */
203     switch (AcpiNsGetType (Info->Node))
204     {
205     case ACPI_TYPE_DEVICE:
206     case ACPI_TYPE_EVENT:
207     case ACPI_TYPE_MUTEX:
208     case ACPI_TYPE_REGION:
209     case ACPI_TYPE_THERMAL:
210     case ACPI_TYPE_LOCAL_SCOPE:
211         /*
212          * 1) Disallow evaluation of certain object types. For these,
213          *    object evaluation is undefined and not supported.
214          */
215         ACPI_ERROR ((AE_INFO,
216             "%s: Evaluation of object type [%s] is not supported",
217             Info->FullPathname,
218             AcpiUtGetTypeName (Info->Node->Type)));
219
220         Status = AE_TYPE;
221         goto Cleanup;
222
223     case ACPI_TYPE_METHOD:
224         /*
225          * 2) Object is a control method - execute it
226          */
227
228         /* Verify that there is a method object associated with this node */
229
230         if (!Info->ObjDesc)
231         {
232             ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object",
233                 Info->FullPathname));
234             Status = AE_NULL_OBJECT;
235             goto Cleanup;
236         }
237
238         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
239             "**** Execute method [%s] at AML address %p length %X\n",
240             Info->FullPathname,
241             Info->ObjDesc->Method.AmlStart + 1,
242             Info->ObjDesc->Method.AmlLength - 1));
243
244         /*
245          * Any namespace deletion must acquire both the namespace and
246          * interpreter locks to ensure that no thread is using the portion of
247          * the namespace that is being deleted.
248          *
249          * Execute the method via the interpreter. The interpreter is locked
250          * here before calling into the AML parser
251          */
252         AcpiExEnterInterpreter ();
253         Status = AcpiPsExecuteMethod (Info);
254         AcpiExExitInterpreter ();
255         break;
256
257     default:
258         /*
259          * 3) All other non-method objects -- get the current object value
260          */
261
262         /*
263          * Some objects require additional resolution steps (e.g., the Node
264          * may be a field that must be read, etc.) -- we can't just grab
265          * the object out of the node.
266          *
267          * Use ResolveNodeToValue() to get the associated value.
268          *
269          * NOTE: we can get away with passing in NULL for a walk state because
270          * the Node is guaranteed to not be a reference to either a method
271          * local or a method argument (because this interface is never called
272          * from a running method.)
273          *
274          * Even though we do not directly invoke the interpreter for object
275          * resolution, we must lock it because we could access an OpRegion.
276          * The OpRegion access code assumes that the interpreter is locked.
277          */
278         AcpiExEnterInterpreter ();
279
280         /* TBD: ResolveNodeToValue has a strange interface, fix */
281
282         Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node);
283
284         Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR (
285             ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL);
286         AcpiExExitInterpreter ();
287
288         if (ACPI_FAILURE (Status))
289         {
290             goto Cleanup;
291         }
292
293         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n",
294             Info->ReturnObject,
295             AcpiUtGetObjectTypeName (Info->ReturnObject)));
296
297         Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */
298         break;
299     }
300
301     /*
302      * For predefined names, check the return value against the ACPI
303      * specification. Some incorrect return value types are repaired.
304      */
305     (void) AcpiNsCheckReturnValue (Info->Node, Info, Info->ParamCount,
306         Status, &Info->ReturnObject);
307
308     /* Check if there is a return value that must be dealt with */
309
310     if (Status == AE_CTRL_RETURN_VALUE)
311     {
312         /* If caller does not want the return value, delete it */
313
314         if (Info->Flags & ACPI_IGNORE_RETURN_VALUE)
315         {
316             AcpiUtRemoveReference (Info->ReturnObject);
317             Info->ReturnObject = NULL;
318         }
319
320         /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
321
322         Status = AE_OK;
323     }
324
325     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
326         "*** Completed evaluation of object %s ***\n",
327         Info->RelativePathname));
328
329 Cleanup:
330     /*
331      * Namespace was unlocked by the handling AcpiNs* function, so we
332      * just free the pathname and return
333      */
334     ACPI_FREE (Info->FullPathname);
335     Info->FullPathname = NULL;
336     return_ACPI_STATUS (Status);
337 }
338
339
340 /*******************************************************************************
341  *
342  * FUNCTION:    AcpiNsExecModuleCodeList
343  *
344  * PARAMETERS:  None
345  *
346  * RETURN:      None. Exceptions during method execution are ignored, since
347  *              we cannot abort a table load.
348  *
349  * DESCRIPTION: Execute all elements of the global module-level code list.
350  *              Each element is executed as a single control method.
351  *
352  ******************************************************************************/
353
354 void
355 AcpiNsExecModuleCodeList (
356     void)
357 {
358     ACPI_OPERAND_OBJECT     *Prev;
359     ACPI_OPERAND_OBJECT     *Next;
360     ACPI_EVALUATE_INFO      *Info;
361     UINT32                  MethodCount = 0;
362
363
364     ACPI_FUNCTION_TRACE (NsExecModuleCodeList);
365
366
367     /* Exit now if the list is empty */
368
369     Next = AcpiGbl_ModuleCodeList;
370     if (!Next)
371     {
372         return_VOID;
373     }
374
375     /* Allocate the evaluation information block */
376
377     Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO));
378     if (!Info)
379     {
380         return_VOID;
381     }
382
383     /* Walk the list, executing each "method" */
384
385     while (Next)
386     {
387         Prev = Next;
388         Next = Next->Method.Mutex;
389
390         /* Clear the link field and execute the method */
391
392         Prev->Method.Mutex = NULL;
393         AcpiNsExecModuleCode (Prev, Info);
394         MethodCount++;
395
396         /* Delete the (temporary) method object */
397
398         AcpiUtRemoveReference (Prev);
399     }
400
401     ACPI_INFO ((AE_INFO,
402         "Executed %u blocks of module-level executable AML code",
403         MethodCount));
404
405     ACPI_FREE (Info);
406     AcpiGbl_ModuleCodeList = NULL;
407     return_VOID;
408 }
409
410
411 /*******************************************************************************
412  *
413  * FUNCTION:    AcpiNsExecModuleCode
414  *
415  * PARAMETERS:  MethodObj           - Object container for the module-level code
416  *              Info                - Info block for method evaluation
417  *
418  * RETURN:      None. Exceptions during method execution are ignored, since
419  *              we cannot abort a table load.
420  *
421  * DESCRIPTION: Execute a control method containing a block of module-level
422  *              executable AML code. The control method is temporarily
423  *              installed to the root node, then evaluated.
424  *
425  ******************************************************************************/
426
427 static void
428 AcpiNsExecModuleCode (
429     ACPI_OPERAND_OBJECT     *MethodObj,
430     ACPI_EVALUATE_INFO      *Info)
431 {
432     ACPI_OPERAND_OBJECT     *ParentObj;
433     ACPI_NAMESPACE_NODE     *ParentNode;
434     ACPI_OBJECT_TYPE        Type;
435     ACPI_STATUS             Status;
436
437
438     ACPI_FUNCTION_TRACE (NsExecModuleCode);
439
440
441     /*
442      * Get the parent node. We cheat by using the NextObject field
443      * of the method object descriptor.
444      */
445     ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
446                     MethodObj->Method.NextObject);
447     Type = AcpiNsGetType (ParentNode);
448
449     /*
450      * Get the region handler and save it in the method object. We may need
451      * this if an operation region declaration causes a _REG method to be run.
452      *
453      * We can't do this in AcpiPsLinkModuleCode because
454      * AcpiGbl_RootNode->Object is NULL at PASS1.
455      */
456     if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object)
457     {
458         MethodObj->Method.Dispatch.Handler =
459             ParentNode->Object->Device.Handler;
460     }
461
462     /* Must clear NextObject (AcpiNsAttachObject needs the field) */
463
464     MethodObj->Method.NextObject = NULL;
465
466     /* Initialize the evaluation information block */
467
468     ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
469     Info->PrefixNode = ParentNode;
470
471     /*
472      * Get the currently attached parent object. Add a reference, because the
473      * ref count will be decreased when the method object is installed to
474      * the parent node.
475      */
476     ParentObj = AcpiNsGetAttachedObject (ParentNode);
477     if (ParentObj)
478     {
479         AcpiUtAddReference (ParentObj);
480     }
481
482     /* Install the method (module-level code) in the parent node */
483
484     Status = AcpiNsAttachObject (ParentNode, MethodObj,
485                 ACPI_TYPE_METHOD);
486     if (ACPI_FAILURE (Status))
487     {
488         goto Exit;
489     }
490
491     /* Execute the parent node as a control method */
492
493     Status = AcpiNsEvaluate (Info);
494
495     ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n",
496         MethodObj->Method.AmlStart));
497
498     /* Delete a possible implicit return value (in slack mode) */
499
500     if (Info->ReturnObject)
501     {
502         AcpiUtRemoveReference (Info->ReturnObject);
503     }
504
505     /* Detach the temporary method object */
506
507     AcpiNsDetachObject (ParentNode);
508
509     /* Restore the original parent object */
510
511     if (ParentObj)
512     {
513         Status = AcpiNsAttachObject (ParentNode, ParentObj, Type);
514     }
515     else
516     {
517         ParentNode->Type = (UINT8) Type;
518     }
519
520 Exit:
521     if (ParentObj)
522     {
523         AcpiUtRemoveReference (ParentObj);
524     }
525     return_VOID;
526 }