xref: /freebsd/sys/contrib/dev/acpica/components/utilities/uteval.c (revision efe3b0de1438e7a8473d92f2be57072394559e3c)
1 /******************************************************************************
2  *
3  * Module Name: uteval - Object evaluation
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acnamesp.h>
47 
48 
49 #define _COMPONENT          ACPI_UTILITIES
50         ACPI_MODULE_NAME    ("uteval")
51 
52 
53 /*******************************************************************************
54  *
55  * FUNCTION:    AcpiUtEvaluateObject
56  *
57  * PARAMETERS:  PrefixNode          - Starting node
58  *              Path                - Path to object from starting node
59  *              ExpectedReturnTypes - Bitmap of allowed return types
60  *              ReturnDesc          - Where a return value is stored
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Evaluates a namespace object and verifies the type of the
65  *              return object. Common code that simplifies accessing objects
66  *              that have required return objects of fixed types.
67  *
68  *              NOTE: Internal function, no parameter validation
69  *
70  ******************************************************************************/
71 
72 ACPI_STATUS
73 AcpiUtEvaluateObject (
74     ACPI_NAMESPACE_NODE     *PrefixNode,
75     const char              *Path,
76     UINT32                  ExpectedReturnBtypes,
77     ACPI_OPERAND_OBJECT     **ReturnDesc)
78 {
79     ACPI_EVALUATE_INFO      *Info;
80     ACPI_STATUS             Status;
81     UINT32                  ReturnBtype;
82 
83 
84     ACPI_FUNCTION_TRACE (UtEvaluateObject);
85 
86 
87     /* Allocate the evaluation information block */
88 
89     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
90     if (!Info)
91     {
92         return_ACPI_STATUS (AE_NO_MEMORY);
93     }
94 
95     Info->PrefixNode = PrefixNode;
96     Info->RelativePathname = Path;
97 
98     /* Evaluate the object/method */
99 
100     Status = AcpiNsEvaluate (Info);
101     if (ACPI_FAILURE (Status))
102     {
103         if (Status == AE_NOT_FOUND)
104         {
105             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
106                 AcpiUtGetNodeName (PrefixNode), Path));
107         }
108         else
109         {
110             ACPI_ERROR_METHOD ("Method execution failed",
111                 PrefixNode, Path, Status);
112         }
113 
114         goto Cleanup;
115     }
116 
117     /* Did we get a return object? */
118 
119     if (!Info->ReturnObject)
120     {
121         if (ExpectedReturnBtypes)
122         {
123             ACPI_ERROR_METHOD ("No object was returned from",
124                 PrefixNode, Path, AE_NOT_EXIST);
125 
126             Status = AE_NOT_EXIST;
127         }
128 
129         goto Cleanup;
130     }
131 
132     /* Map the return object type to the bitmapped type */
133 
134     switch ((Info->ReturnObject)->Common.Type)
135     {
136     case ACPI_TYPE_INTEGER:
137 
138         ReturnBtype = ACPI_BTYPE_INTEGER;
139         break;
140 
141     case ACPI_TYPE_BUFFER:
142 
143         ReturnBtype = ACPI_BTYPE_BUFFER;
144         break;
145 
146     case ACPI_TYPE_STRING:
147 
148         ReturnBtype = ACPI_BTYPE_STRING;
149         break;
150 
151     case ACPI_TYPE_PACKAGE:
152 
153         ReturnBtype = ACPI_BTYPE_PACKAGE;
154         break;
155 
156     default:
157 
158         ReturnBtype = 0;
159         break;
160     }
161 
162     if ((AcpiGbl_EnableInterpreterSlack) &&
163         (!ExpectedReturnBtypes))
164     {
165         /*
166          * We received a return object, but one was not expected. This can
167          * happen frequently if the "implicit return" feature is enabled.
168          * Just delete the return object and return AE_OK.
169          */
170         AcpiUtRemoveReference (Info->ReturnObject);
171         goto Cleanup;
172     }
173 
174     /* Is the return object one of the expected types? */
175 
176     if (!(ExpectedReturnBtypes & ReturnBtype))
177     {
178         ACPI_ERROR_METHOD ("Return object type is incorrect",
179             PrefixNode, Path, AE_TYPE);
180 
181         ACPI_ERROR ((AE_INFO,
182             "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
183             Path, AcpiUtGetObjectTypeName (Info->ReturnObject),
184             ExpectedReturnBtypes));
185 
186         /* On error exit, we must delete the return object */
187 
188         AcpiUtRemoveReference (Info->ReturnObject);
189         Status = AE_TYPE;
190         goto Cleanup;
191     }
192 
193     /* Object type is OK, return it */
194 
195     *ReturnDesc = Info->ReturnObject;
196 
197 Cleanup:
198     ACPI_FREE (Info);
199     return_ACPI_STATUS (Status);
200 }
201 
202 
203 /*******************************************************************************
204  *
205  * FUNCTION:    AcpiUtEvaluateNumericObject
206  *
207  * PARAMETERS:  ObjectName          - Object name to be evaluated
208  *              DeviceNode          - Node for the device
209  *              Value               - Where the value is returned
210  *
211  * RETURN:      Status
212  *
213  * DESCRIPTION: Evaluates a numeric namespace object for a selected device
214  *              and stores result in *Value.
215  *
216  *              NOTE: Internal function, no parameter validation
217  *
218  ******************************************************************************/
219 
220 ACPI_STATUS
221 AcpiUtEvaluateNumericObject (
222     const char              *ObjectName,
223     ACPI_NAMESPACE_NODE     *DeviceNode,
224     UINT64                  *Value)
225 {
226     ACPI_OPERAND_OBJECT     *ObjDesc;
227     ACPI_STATUS             Status;
228 
229 
230     ACPI_FUNCTION_TRACE (UtEvaluateNumericObject);
231 
232 
233     Status = AcpiUtEvaluateObject (DeviceNode, ObjectName,
234         ACPI_BTYPE_INTEGER, &ObjDesc);
235     if (ACPI_FAILURE (Status))
236     {
237         return_ACPI_STATUS (Status);
238     }
239 
240     /* Get the returned Integer */
241 
242     *Value = ObjDesc->Integer.Value;
243 
244     /* On exit, we must delete the return object */
245 
246     AcpiUtRemoveReference (ObjDesc);
247     return_ACPI_STATUS (Status);
248 }
249 
250 
251 /*******************************************************************************
252  *
253  * FUNCTION:    AcpiUtExecute_STA
254  *
255  * PARAMETERS:  DeviceNode          - Node for the device
256  *              Flags               - Where the status flags are returned
257  *
258  * RETURN:      Status
259  *
260  * DESCRIPTION: Executes _STA for selected device and stores results in
261  *              *Flags. If _STA does not exist, then the device is assumed
262  *              to be present/functional/enabled (as per the ACPI spec).
263  *
264  *              NOTE: Internal function, no parameter validation
265  *
266  ******************************************************************************/
267 
268 ACPI_STATUS
269 AcpiUtExecute_STA (
270     ACPI_NAMESPACE_NODE     *DeviceNode,
271     UINT32                  *Flags)
272 {
273     ACPI_OPERAND_OBJECT     *ObjDesc;
274     ACPI_STATUS             Status;
275 
276 
277     ACPI_FUNCTION_TRACE (UtExecute_STA);
278 
279 
280     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA,
281         ACPI_BTYPE_INTEGER, &ObjDesc);
282     if (ACPI_FAILURE (Status))
283     {
284         if (AE_NOT_FOUND == Status)
285         {
286             /*
287              * if _STA does not exist, then (as per the ACPI specification),
288              * the returned flags will indicate that the device is present,
289              * functional, and enabled.
290              */
291             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
292                 "_STA on %4.4s was not found, assuming device is present\n",
293                 AcpiUtGetNodeName (DeviceNode)));
294 
295             *Flags = ACPI_UINT32_MAX;
296             Status = AE_OK;
297         }
298 
299         return_ACPI_STATUS (Status);
300     }
301 
302     /* Extract the status flags */
303 
304     *Flags = (UINT32) ObjDesc->Integer.Value;
305 
306     /* On exit, we must delete the return object */
307 
308     AcpiUtRemoveReference (ObjDesc);
309     return_ACPI_STATUS (Status);
310 }
311 
312 
313 /*******************************************************************************
314  *
315  * FUNCTION:    AcpiUtExecutePowerMethods
316  *
317  * PARAMETERS:  DeviceNode          - Node for the device
318  *              MethodNames         - Array of power method names
319  *              MethodCount         - Number of methods to execute
320  *              OutValues           - Where the power method values are returned
321  *
322  * RETURN:      Status, OutValues
323  *
324  * DESCRIPTION: Executes the specified power methods for the device and returns
325  *              the result(s).
326  *
327  *              NOTE: Internal function, no parameter validation
328  *
329  ******************************************************************************/
330 
331 ACPI_STATUS
332 AcpiUtExecutePowerMethods (
333     ACPI_NAMESPACE_NODE     *DeviceNode,
334     const char              **MethodNames,
335     UINT8                   MethodCount,
336     UINT8                   *OutValues)
337 {
338     ACPI_OPERAND_OBJECT     *ObjDesc;
339     ACPI_STATUS             Status;
340     ACPI_STATUS             FinalStatus = AE_NOT_FOUND;
341     UINT32                  i;
342 
343 
344     ACPI_FUNCTION_TRACE (UtExecutePowerMethods);
345 
346 
347     for (i = 0; i < MethodCount; i++)
348     {
349         /*
350          * Execute the power method (_SxD or _SxW). The only allowable
351          * return type is an Integer.
352          */
353         Status = AcpiUtEvaluateObject (DeviceNode,
354             ACPI_CAST_PTR (char, MethodNames[i]),
355             ACPI_BTYPE_INTEGER, &ObjDesc);
356         if (ACPI_SUCCESS (Status))
357         {
358             OutValues[i] = (UINT8) ObjDesc->Integer.Value;
359 
360             /* Delete the return object */
361 
362             AcpiUtRemoveReference (ObjDesc);
363             FinalStatus = AE_OK;            /* At least one value is valid */
364             continue;
365         }
366 
367         OutValues[i] = ACPI_UINT8_MAX;
368         if (Status == AE_NOT_FOUND)
369         {
370             continue; /* Ignore if not found */
371         }
372 
373         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Failed %s on Device %4.4s, %s\n",
374             ACPI_CAST_PTR (char, MethodNames[i]),
375             AcpiUtGetNodeName (DeviceNode), AcpiFormatException (Status)));
376     }
377 
378     return_ACPI_STATUS (FinalStatus);
379 }
380