Sync ACPICA with Intel's version 20141107.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / parser / psxface.c
1 /******************************************************************************
2  *
3  * Module Name: psxface - Parser external interfaces
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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "acdispat.h"
48 #include "acinterp.h"
49 #include "actables.h"
50
51
52 #define _COMPONENT          ACPI_PARSER
53         ACPI_MODULE_NAME    ("psxface")
54
55 /* Local Prototypes */
56
57 static void
58 AcpiPsStartTrace (
59     ACPI_EVALUATE_INFO      *Info);
60
61 static void
62 AcpiPsStopTrace (
63     ACPI_EVALUATE_INFO      *Info);
64
65 static void
66 AcpiPsUpdateParameterList (
67     ACPI_EVALUATE_INFO      *Info,
68     UINT16                  Action);
69
70
71 /*******************************************************************************
72  *
73  * FUNCTION:    AcpiDebugTrace
74  *
75  * PARAMETERS:  MethodName      - Valid ACPI name string
76  *              DebugLevel      - Optional level mask. 0 to use default
77  *              DebugLayer      - Optional layer mask. 0 to use default
78  *              Flags           - bit 1: one shot(1) or persistent(0)
79  *
80  * RETURN:      Status
81  *
82  * DESCRIPTION: External interface to enable debug tracing during control
83  *              method execution
84  *
85  ******************************************************************************/
86
87 ACPI_STATUS
88 AcpiDebugTrace (
89     char                    *Name,
90     UINT32                  DebugLevel,
91     UINT32                  DebugLayer,
92     UINT32                  Flags)
93 {
94     ACPI_STATUS             Status;
95
96
97     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
98     if (ACPI_FAILURE (Status))
99     {
100         return (Status);
101     }
102
103     /* TBDs: Validate name, allow full path or just nameseg */
104
105     AcpiGbl_TraceMethodName = *ACPI_CAST_PTR (UINT32, Name);
106     AcpiGbl_TraceFlags = Flags;
107
108     if (DebugLevel)
109     {
110         AcpiGbl_TraceDbgLevel = DebugLevel;
111     }
112     if (DebugLayer)
113     {
114         AcpiGbl_TraceDbgLayer = DebugLayer;
115     }
116
117     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
118     return (AE_OK);
119 }
120
121
122 /*******************************************************************************
123  *
124  * FUNCTION:    AcpiPsStartTrace
125  *
126  * PARAMETERS:  Info        - Method info struct
127  *
128  * RETURN:      None
129  *
130  * DESCRIPTION: Start control method execution trace
131  *
132  ******************************************************************************/
133
134 static void
135 AcpiPsStartTrace (
136     ACPI_EVALUATE_INFO      *Info)
137 {
138     ACPI_STATUS             Status;
139
140
141     ACPI_FUNCTION_ENTRY ();
142
143
144     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
145     if (ACPI_FAILURE (Status))
146     {
147         return;
148     }
149
150     if ((!AcpiGbl_TraceMethodName) ||
151         (AcpiGbl_TraceMethodName != Info->Node->Name.Integer))
152     {
153         goto Exit;
154     }
155
156     AcpiGbl_OriginalDbgLevel = AcpiDbgLevel;
157     AcpiGbl_OriginalDbgLayer = AcpiDbgLayer;
158
159     AcpiDbgLevel = 0x00FFFFFF;
160     AcpiDbgLayer = ACPI_UINT32_MAX;
161
162     if (AcpiGbl_TraceDbgLevel)
163     {
164         AcpiDbgLevel = AcpiGbl_TraceDbgLevel;
165     }
166     if (AcpiGbl_TraceDbgLayer)
167     {
168         AcpiDbgLayer = AcpiGbl_TraceDbgLayer;
169     }
170
171
172 Exit:
173     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
174 }
175
176
177 /*******************************************************************************
178  *
179  * FUNCTION:    AcpiPsStopTrace
180  *
181  * PARAMETERS:  Info        - Method info struct
182  *
183  * RETURN:      None
184  *
185  * DESCRIPTION: Stop control method execution trace
186  *
187  ******************************************************************************/
188
189 static void
190 AcpiPsStopTrace (
191     ACPI_EVALUATE_INFO      *Info)
192 {
193     ACPI_STATUS             Status;
194
195
196     ACPI_FUNCTION_ENTRY ();
197
198
199     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
200     if (ACPI_FAILURE (Status))
201     {
202         return;
203     }
204
205     if ((!AcpiGbl_TraceMethodName) ||
206         (AcpiGbl_TraceMethodName != Info->Node->Name.Integer))
207     {
208         goto Exit;
209     }
210
211     /* Disable further tracing if type is one-shot */
212
213     if (AcpiGbl_TraceFlags & 1)
214     {
215         AcpiGbl_TraceMethodName = 0;
216         AcpiGbl_TraceDbgLevel = 0;
217         AcpiGbl_TraceDbgLayer = 0;
218     }
219
220     AcpiDbgLevel = AcpiGbl_OriginalDbgLevel;
221     AcpiDbgLayer = AcpiGbl_OriginalDbgLayer;
222
223 Exit:
224     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
225 }
226
227
228 /*******************************************************************************
229  *
230  * FUNCTION:    AcpiPsExecuteMethod
231  *
232  * PARAMETERS:  Info            - Method info block, contains:
233  *                  Node            - Method Node to execute
234  *                  ObjDesc         - Method object
235  *                  Parameters      - List of parameters to pass to the method,
236  *                                    terminated by NULL. Params itself may be
237  *                                    NULL if no parameters are being passed.
238  *                  ReturnObject    - Where to put method's return value (if
239  *                                    any). If NULL, no value is returned.
240  *                  ParameterType   - Type of Parameter list
241  *                  ReturnObject    - Where to put method's return value (if
242  *                                    any). If NULL, no value is returned.
243  *                  PassNumber      - Parse or execute pass
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Execute a control method
248  *
249  ******************************************************************************/
250
251 ACPI_STATUS
252 AcpiPsExecuteMethod (
253     ACPI_EVALUATE_INFO      *Info)
254 {
255     ACPI_STATUS             Status;
256     ACPI_PARSE_OBJECT       *Op;
257     ACPI_WALK_STATE         *WalkState;
258
259
260     ACPI_FUNCTION_TRACE (PsExecuteMethod);
261
262
263     /* Quick validation of DSDT header */
264
265     AcpiTbCheckDsdtHeader ();
266
267     /* Validate the Info and method Node */
268
269     if (!Info || !Info->Node)
270     {
271         return_ACPI_STATUS (AE_NULL_ENTRY);
272     }
273
274     /* Init for new method, wait on concurrency semaphore */
275
276     Status = AcpiDsBeginMethodExecution (Info->Node, Info->ObjDesc, NULL);
277     if (ACPI_FAILURE (Status))
278     {
279         return_ACPI_STATUS (Status);
280     }
281
282     /*
283      * The caller "owns" the parameters, so give each one an extra reference
284      */
285     AcpiPsUpdateParameterList (Info, REF_INCREMENT);
286
287     /* Begin tracing if requested */
288
289     AcpiPsStartTrace (Info);
290
291     /*
292      * Execute the method. Performs parse simultaneously
293      */
294     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
295         "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
296         Info->Node->Name.Ascii, Info->Node, Info->ObjDesc));
297
298     /* Create and init a Root Node */
299
300     Op = AcpiPsCreateScopeOp ();
301     if (!Op)
302     {
303         Status = AE_NO_MEMORY;
304         goto Cleanup;
305     }
306
307     /* Create and initialize a new walk state */
308
309     Info->PassNumber = ACPI_IMODE_EXECUTE;
310     WalkState = AcpiDsCreateWalkState (
311                     Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL);
312     if (!WalkState)
313     {
314         Status = AE_NO_MEMORY;
315         goto Cleanup;
316     }
317
318     Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node,
319                 Info->ObjDesc->Method.AmlStart,
320                 Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber);
321     if (ACPI_FAILURE (Status))
322     {
323         AcpiDsDeleteWalkState (WalkState);
324         goto Cleanup;
325     }
326
327     if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
328     {
329         WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL;
330     }
331
332     /* Invoke an internal method if necessary */
333
334     if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
335     {
336         Status = Info->ObjDesc->Method.Dispatch.Implementation (WalkState);
337         Info->ReturnObject = WalkState->ReturnDesc;
338
339         /* Cleanup states */
340
341         AcpiDsScopeStackClear (WalkState);
342         AcpiPsCleanupScope (&WalkState->ParserState);
343         AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
344         AcpiDsDeleteWalkState (WalkState);
345         goto Cleanup;
346     }
347
348     /*
349      * Start method evaluation with an implicit return of zero.
350      * This is done for Windows compatibility.
351      */
352     if (AcpiGbl_EnableInterpreterSlack)
353     {
354         WalkState->ImplicitReturnObj =
355             AcpiUtCreateIntegerObject ((UINT64) 0);
356         if (!WalkState->ImplicitReturnObj)
357         {
358             Status = AE_NO_MEMORY;
359             AcpiDsDeleteWalkState (WalkState);
360             goto Cleanup;
361         }
362     }
363
364     /* Parse the AML */
365
366     Status = AcpiPsParseAml (WalkState);
367
368     /* WalkState was deleted by ParseAml */
369
370 Cleanup:
371     AcpiPsDeleteParseTree (Op);
372
373     /* End optional tracing */
374
375     AcpiPsStopTrace (Info);
376
377     /* Take away the extra reference that we gave the parameters above */
378
379     AcpiPsUpdateParameterList (Info, REF_DECREMENT);
380
381     /* Exit now if error above */
382
383     if (ACPI_FAILURE (Status))
384     {
385         return_ACPI_STATUS (Status);
386     }
387
388     /*
389      * If the method has returned an object, signal this to the caller with
390      * a control exception code
391      */
392     if (Info->ReturnObject)
393     {
394         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
395             Info->ReturnObject));
396         ACPI_DUMP_STACK_ENTRY (Info->ReturnObject);
397
398         Status = AE_CTRL_RETURN_VALUE;
399     }
400
401     return_ACPI_STATUS (Status);
402 }
403
404
405 /*******************************************************************************
406  *
407  * FUNCTION:    AcpiPsUpdateParameterList
408  *
409  * PARAMETERS:  Info            - See ACPI_EVALUATE_INFO
410  *                                (Used: ParameterType and Parameters)
411  *              Action          - Add or Remove reference
412  *
413  * RETURN:      Status
414  *
415  * DESCRIPTION: Update reference count on all method parameter objects
416  *
417  ******************************************************************************/
418
419 static void
420 AcpiPsUpdateParameterList (
421     ACPI_EVALUATE_INFO      *Info,
422     UINT16                  Action)
423 {
424     UINT32                  i;
425
426
427     if (Info->Parameters)
428     {
429         /* Update reference count for each parameter */
430
431         for (i = 0; Info->Parameters[i]; i++)
432         {
433             /* Ignore errors, just do them all */
434
435             (void) AcpiUtUpdateObjectReference (Info->Parameters[i], Action);
436         }
437     }
438 }