1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: uteval - Object evaluation |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acnamesp.h" |
13 | |
14 | #define _COMPONENT ACPI_UTILITIES |
15 | ACPI_MODULE_NAME("uteval" ) |
16 | |
17 | /******************************************************************************* |
18 | * |
19 | * FUNCTION: acpi_ut_evaluate_object |
20 | * |
21 | * PARAMETERS: prefix_node - Starting node |
22 | * path - Path to object from starting node |
23 | * expected_return_types - Bitmap of allowed return types |
24 | * return_desc - Where a return value is stored |
25 | * |
26 | * RETURN: Status |
27 | * |
28 | * DESCRIPTION: Evaluates a namespace object and verifies the type of the |
29 | * return object. Common code that simplifies accessing objects |
30 | * that have required return objects of fixed types. |
31 | * |
32 | * NOTE: Internal function, no parameter validation |
33 | * |
34 | ******************************************************************************/ |
35 | |
36 | acpi_status |
37 | acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, |
38 | const char *path, |
39 | u32 expected_return_btypes, |
40 | union acpi_operand_object **return_desc) |
41 | { |
42 | struct acpi_evaluate_info *info; |
43 | acpi_status status; |
44 | u32 return_btype; |
45 | |
46 | ACPI_FUNCTION_TRACE(ut_evaluate_object); |
47 | |
48 | /* Allocate the evaluation information block */ |
49 | |
50 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); |
51 | if (!info) { |
52 | return_ACPI_STATUS(AE_NO_MEMORY); |
53 | } |
54 | |
55 | info->prefix_node = prefix_node; |
56 | info->relative_pathname = path; |
57 | |
58 | /* Evaluate the object/method */ |
59 | |
60 | status = acpi_ns_evaluate(info); |
61 | if (ACPI_FAILURE(status)) { |
62 | if (status == AE_NOT_FOUND) { |
63 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
64 | "[%4.4s.%s] was not found\n" , |
65 | acpi_ut_get_node_name(prefix_node), |
66 | path)); |
67 | } else { |
68 | ACPI_ERROR_METHOD("Method execution failed" , |
69 | prefix_node, path, status); |
70 | } |
71 | |
72 | goto cleanup; |
73 | } |
74 | |
75 | /* Did we get a return object? */ |
76 | |
77 | if (!info->return_object) { |
78 | if (expected_return_btypes) { |
79 | ACPI_ERROR_METHOD("No object was returned from" , |
80 | prefix_node, path, AE_NOT_EXIST); |
81 | |
82 | status = AE_NOT_EXIST; |
83 | } |
84 | |
85 | goto cleanup; |
86 | } |
87 | |
88 | /* Map the return object type to the bitmapped type */ |
89 | |
90 | switch ((info->return_object)->common.type) { |
91 | case ACPI_TYPE_INTEGER: |
92 | |
93 | return_btype = ACPI_BTYPE_INTEGER; |
94 | break; |
95 | |
96 | case ACPI_TYPE_BUFFER: |
97 | |
98 | return_btype = ACPI_BTYPE_BUFFER; |
99 | break; |
100 | |
101 | case ACPI_TYPE_STRING: |
102 | |
103 | return_btype = ACPI_BTYPE_STRING; |
104 | break; |
105 | |
106 | case ACPI_TYPE_PACKAGE: |
107 | |
108 | return_btype = ACPI_BTYPE_PACKAGE; |
109 | break; |
110 | |
111 | default: |
112 | |
113 | return_btype = 0; |
114 | break; |
115 | } |
116 | |
117 | if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { |
118 | /* |
119 | * We received a return object, but one was not expected. This can |
120 | * happen frequently if the "implicit return" feature is enabled. |
121 | * Just delete the return object and return AE_OK. |
122 | */ |
123 | acpi_ut_remove_reference(object: info->return_object); |
124 | goto cleanup; |
125 | } |
126 | |
127 | /* Is the return object one of the expected types? */ |
128 | |
129 | if (!(expected_return_btypes & return_btype)) { |
130 | ACPI_ERROR_METHOD("Return object type is incorrect" , |
131 | prefix_node, path, AE_TYPE); |
132 | |
133 | ACPI_ERROR((AE_INFO, |
134 | "Type returned from %s was incorrect: %s, expected Btypes: 0x%X" , |
135 | path, |
136 | acpi_ut_get_object_type_name(info->return_object), |
137 | expected_return_btypes)); |
138 | |
139 | /* On error exit, we must delete the return object */ |
140 | |
141 | acpi_ut_remove_reference(object: info->return_object); |
142 | status = AE_TYPE; |
143 | goto cleanup; |
144 | } |
145 | |
146 | /* Object type is OK, return it */ |
147 | |
148 | *return_desc = info->return_object; |
149 | |
150 | cleanup: |
151 | ACPI_FREE(info); |
152 | return_ACPI_STATUS(status); |
153 | } |
154 | |
155 | /******************************************************************************* |
156 | * |
157 | * FUNCTION: acpi_ut_evaluate_numeric_object |
158 | * |
159 | * PARAMETERS: object_name - Object name to be evaluated |
160 | * device_node - Node for the device |
161 | * value - Where the value is returned |
162 | * |
163 | * RETURN: Status |
164 | * |
165 | * DESCRIPTION: Evaluates a numeric namespace object for a selected device |
166 | * and stores result in *Value. |
167 | * |
168 | * NOTE: Internal function, no parameter validation |
169 | * |
170 | ******************************************************************************/ |
171 | |
172 | acpi_status |
173 | acpi_ut_evaluate_numeric_object(const char *object_name, |
174 | struct acpi_namespace_node *device_node, |
175 | u64 *value) |
176 | { |
177 | union acpi_operand_object *obj_desc; |
178 | acpi_status status; |
179 | |
180 | ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); |
181 | |
182 | status = acpi_ut_evaluate_object(prefix_node: device_node, path: object_name, |
183 | ACPI_BTYPE_INTEGER, return_desc: &obj_desc); |
184 | if (ACPI_FAILURE(status)) { |
185 | return_ACPI_STATUS(status); |
186 | } |
187 | |
188 | /* Get the returned Integer */ |
189 | |
190 | *value = obj_desc->integer.value; |
191 | |
192 | /* On exit, we must delete the return object */ |
193 | |
194 | acpi_ut_remove_reference(object: obj_desc); |
195 | return_ACPI_STATUS(status); |
196 | } |
197 | |
198 | /******************************************************************************* |
199 | * |
200 | * FUNCTION: acpi_ut_execute_STA |
201 | * |
202 | * PARAMETERS: device_node - Node for the device |
203 | * flags - Where the status flags are returned |
204 | * |
205 | * RETURN: Status |
206 | * |
207 | * DESCRIPTION: Executes _STA for selected device and stores results in |
208 | * *Flags. If _STA does not exist, then the device is assumed |
209 | * to be present/functional/enabled (as per the ACPI spec). |
210 | * |
211 | * NOTE: Internal function, no parameter validation |
212 | * |
213 | ******************************************************************************/ |
214 | |
215 | acpi_status |
216 | acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) |
217 | { |
218 | union acpi_operand_object *obj_desc; |
219 | acpi_status status; |
220 | |
221 | ACPI_FUNCTION_TRACE(ut_execute_STA); |
222 | |
223 | status = acpi_ut_evaluate_object(prefix_node: device_node, METHOD_NAME__STA, |
224 | ACPI_BTYPE_INTEGER, return_desc: &obj_desc); |
225 | if (ACPI_FAILURE(status)) { |
226 | if (AE_NOT_FOUND == status) { |
227 | /* |
228 | * if _STA does not exist, then (as per the ACPI specification), |
229 | * the returned flags will indicate that the device is present, |
230 | * functional, and enabled. |
231 | */ |
232 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
233 | "_STA on %4.4s was not found, assuming device is present\n" , |
234 | acpi_ut_get_node_name(device_node))); |
235 | |
236 | *flags = ACPI_UINT32_MAX; |
237 | status = AE_OK; |
238 | } |
239 | |
240 | return_ACPI_STATUS(status); |
241 | } |
242 | |
243 | /* Extract the status flags */ |
244 | |
245 | *flags = (u32) obj_desc->integer.value; |
246 | |
247 | /* On exit, we must delete the return object */ |
248 | |
249 | acpi_ut_remove_reference(object: obj_desc); |
250 | return_ACPI_STATUS(status); |
251 | } |
252 | |
253 | /******************************************************************************* |
254 | * |
255 | * FUNCTION: acpi_ut_execute_power_methods |
256 | * |
257 | * PARAMETERS: device_node - Node for the device |
258 | * method_names - Array of power method names |
259 | * method_count - Number of methods to execute |
260 | * out_values - Where the power method values are returned |
261 | * |
262 | * RETURN: Status, out_values |
263 | * |
264 | * DESCRIPTION: Executes the specified power methods for the device and returns |
265 | * the result(s). |
266 | * |
267 | * NOTE: Internal function, no parameter validation |
268 | * |
269 | ******************************************************************************/ |
270 | |
271 | acpi_status |
272 | acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, |
273 | const char **method_names, |
274 | u8 method_count, u8 *out_values) |
275 | { |
276 | union acpi_operand_object *obj_desc; |
277 | acpi_status status; |
278 | acpi_status final_status = AE_NOT_FOUND; |
279 | u32 i; |
280 | |
281 | ACPI_FUNCTION_TRACE(ut_execute_power_methods); |
282 | |
283 | for (i = 0; i < method_count; i++) { |
284 | /* |
285 | * Execute the power method (_sx_d or _sx_w). The only allowable |
286 | * return type is an Integer. |
287 | */ |
288 | status = acpi_ut_evaluate_object(prefix_node: device_node, |
289 | ACPI_CAST_PTR(char, |
290 | method_names[i]), |
291 | ACPI_BTYPE_INTEGER, return_desc: &obj_desc); |
292 | if (ACPI_SUCCESS(status)) { |
293 | out_values[i] = (u8)obj_desc->integer.value; |
294 | |
295 | /* Delete the return object */ |
296 | |
297 | acpi_ut_remove_reference(object: obj_desc); |
298 | final_status = AE_OK; /* At least one value is valid */ |
299 | continue; |
300 | } |
301 | |
302 | out_values[i] = ACPI_UINT8_MAX; |
303 | if (status == AE_NOT_FOUND) { |
304 | continue; /* Ignore if not found */ |
305 | } |
306 | |
307 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
308 | "Failed %s on Device %4.4s, %s\n" , |
309 | ACPI_CAST_PTR(char, method_names[i]), |
310 | acpi_ut_get_node_name(device_node), |
311 | acpi_format_exception(status))); |
312 | } |
313 | |
314 | return_ACPI_STATUS(final_status); |
315 | } |
316 | |