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