1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: nspredef - Validation of ACPI predefined methods and objects |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #define ACPI_CREATE_PREDEFINED_TABLE |
11 | |
12 | #include <acpi/acpi.h> |
13 | #include "accommon.h" |
14 | #include "acnamesp.h" |
15 | #include "acpredef.h" |
16 | |
17 | #define _COMPONENT ACPI_NAMESPACE |
18 | ACPI_MODULE_NAME("nspredef" ) |
19 | |
20 | /******************************************************************************* |
21 | * |
22 | * This module validates predefined ACPI objects that appear in the namespace, |
23 | * at the time they are evaluated (via acpi_evaluate_object). The purpose of this |
24 | * validation is to detect problems with BIOS-exposed predefined ACPI objects |
25 | * before the results are returned to the ACPI-related drivers. |
26 | * |
27 | * There are several areas that are validated: |
28 | * |
29 | * 1) The number of input arguments as defined by the method/object in the |
30 | * ASL is validated against the ACPI specification. |
31 | * 2) The type of the return object (if any) is validated against the ACPI |
32 | * specification. |
33 | * 3) For returned package objects, the count of package elements is |
34 | * validated, as well as the type of each package element. Nested |
35 | * packages are supported. |
36 | * |
37 | * For any problems found, a warning message is issued. |
38 | * |
39 | ******************************************************************************/ |
40 | /* Local prototypes */ |
41 | static acpi_status |
42 | acpi_ns_check_reference(struct acpi_evaluate_info *info, |
43 | union acpi_operand_object *return_object); |
44 | |
45 | static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); |
46 | |
47 | /******************************************************************************* |
48 | * |
49 | * FUNCTION: acpi_ns_check_return_value |
50 | * |
51 | * PARAMETERS: node - Namespace node for the method/object |
52 | * info - Method execution information block |
53 | * user_param_count - Number of parameters actually passed |
54 | * return_status - Status from the object evaluation |
55 | * return_object_ptr - Pointer to the object returned from the |
56 | * evaluation of a method or object |
57 | * |
58 | * RETURN: Status |
59 | * |
60 | * DESCRIPTION: Check the value returned from a predefined name. |
61 | * |
62 | ******************************************************************************/ |
63 | |
64 | acpi_status |
65 | acpi_ns_check_return_value(struct acpi_namespace_node *node, |
66 | struct acpi_evaluate_info *info, |
67 | u32 user_param_count, |
68 | acpi_status return_status, |
69 | union acpi_operand_object **return_object_ptr) |
70 | { |
71 | acpi_status status; |
72 | const union acpi_predefined_info *predefined; |
73 | |
74 | ACPI_FUNCTION_TRACE(ns_check_return_value); |
75 | |
76 | /* If not a predefined name, we cannot validate the return object */ |
77 | |
78 | predefined = info->predefined; |
79 | if (!predefined) { |
80 | return_ACPI_STATUS(AE_OK); |
81 | } |
82 | |
83 | /* |
84 | * If the method failed or did not actually return an object, we cannot |
85 | * validate the return object |
86 | */ |
87 | if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { |
88 | return_ACPI_STATUS(AE_OK); |
89 | } |
90 | |
91 | /* |
92 | * Return value validation and possible repair. |
93 | * |
94 | * 1) Don't perform return value validation/repair if this feature |
95 | * has been disabled via a global option. |
96 | * |
97 | * 2) We have a return value, but if one wasn't expected, just exit, |
98 | * this is not a problem. For example, if the "Implicit Return" |
99 | * feature is enabled, methods will always return a value. |
100 | * |
101 | * 3) If the return value can be of any type, then we cannot perform |
102 | * any validation, just exit. |
103 | */ |
104 | if (acpi_gbl_disable_auto_repair || |
105 | (!predefined->info.expected_btypes) || |
106 | (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { |
107 | return_ACPI_STATUS(AE_OK); |
108 | } |
109 | |
110 | /* |
111 | * Check that the type of the main return object is what is expected |
112 | * for this predefined name |
113 | */ |
114 | status = acpi_ns_check_object_type(info, return_object_ptr, |
115 | expected_btypes: predefined->info.expected_btypes, |
116 | ACPI_NOT_PACKAGE_ELEMENT); |
117 | if (ACPI_FAILURE(status)) { |
118 | goto exit; |
119 | } |
120 | |
121 | /* |
122 | * |
123 | * 4) If there is no return value and it is optional, just return |
124 | * AE_OK (_WAK). |
125 | */ |
126 | if (!(*return_object_ptr)) { |
127 | goto exit; |
128 | } |
129 | |
130 | /* |
131 | * For returned Package objects, check the type of all sub-objects. |
132 | * Note: Package may have been newly created by call above. |
133 | */ |
134 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { |
135 | info->parent_package = *return_object_ptr; |
136 | status = acpi_ns_check_package(info, return_object_ptr); |
137 | if (ACPI_FAILURE(status)) { |
138 | |
139 | /* We might be able to fix some errors */ |
140 | |
141 | if ((status != AE_AML_OPERAND_TYPE) && |
142 | (status != AE_AML_OPERAND_VALUE)) { |
143 | goto exit; |
144 | } |
145 | } |
146 | } |
147 | |
148 | /* |
149 | * The return object was OK, or it was successfully repaired above. |
150 | * Now make some additional checks such as verifying that package |
151 | * objects are sorted correctly (if required) or buffer objects have |
152 | * the correct data width (bytes vs. dwords). These repairs are |
153 | * performed on a per-name basis, i.e., the code is specific to |
154 | * particular predefined names. |
155 | */ |
156 | status = acpi_ns_complex_repairs(info, node, validate_status: status, return_object_ptr); |
157 | |
158 | exit: |
159 | /* |
160 | * If the object validation failed or if we successfully repaired one |
161 | * or more objects, mark the parent node to suppress further warning |
162 | * messages during the next evaluation of the same method/object. |
163 | */ |
164 | if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { |
165 | node->flags |= ANOBJ_EVALUATED; |
166 | } |
167 | |
168 | return_ACPI_STATUS(status); |
169 | } |
170 | |
171 | /******************************************************************************* |
172 | * |
173 | * FUNCTION: acpi_ns_check_object_type |
174 | * |
175 | * PARAMETERS: info - Method execution information block |
176 | * return_object_ptr - Pointer to the object returned from the |
177 | * evaluation of a method or object |
178 | * expected_btypes - Bitmap of expected return type(s) |
179 | * package_index - Index of object within parent package (if |
180 | * applicable - ACPI_NOT_PACKAGE_ELEMENT |
181 | * otherwise) |
182 | * |
183 | * RETURN: Status |
184 | * |
185 | * DESCRIPTION: Check the type of the return object against the expected object |
186 | * type(s). Use of Btype allows multiple expected object types. |
187 | * |
188 | ******************************************************************************/ |
189 | |
190 | acpi_status |
191 | acpi_ns_check_object_type(struct acpi_evaluate_info *info, |
192 | union acpi_operand_object **return_object_ptr, |
193 | u32 expected_btypes, u32 package_index) |
194 | { |
195 | union acpi_operand_object *return_object = *return_object_ptr; |
196 | acpi_status status = AE_OK; |
197 | char type_buffer[96]; /* Room for 10 types */ |
198 | |
199 | /* A Namespace node should not get here, but make sure */ |
200 | |
201 | if (return_object && |
202 | ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { |
203 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
204 | info->node_flags, |
205 | "Invalid return type - Found a Namespace node [%4.4s] type %s" , |
206 | return_object->node.name.ascii, |
207 | acpi_ut_get_type_name(return_object->node. |
208 | type))); |
209 | return (AE_AML_OPERAND_TYPE); |
210 | } |
211 | |
212 | /* |
213 | * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type. |
214 | * The bitmapped type allows multiple possible return types. |
215 | * |
216 | * Note, the cases below must handle all of the possible types returned |
217 | * from all of the predefined names (including elements of returned |
218 | * packages) |
219 | */ |
220 | info->return_btype = acpi_ns_get_bitmapped_type(return_object); |
221 | if (info->return_btype == ACPI_RTYPE_ANY) { |
222 | |
223 | /* Not one of the supported objects, must be incorrect */ |
224 | goto type_error_exit; |
225 | } |
226 | |
227 | /* For reference objects, check that the reference type is correct */ |
228 | |
229 | if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { |
230 | status = acpi_ns_check_reference(info, return_object); |
231 | return (status); |
232 | } |
233 | |
234 | /* Attempt simple repair of the returned object if necessary */ |
235 | |
236 | status = acpi_ns_simple_repair(info, expected_btypes, |
237 | package_index, return_object_ptr); |
238 | if (ACPI_SUCCESS(status)) { |
239 | return (AE_OK); /* Successful repair */ |
240 | } |
241 | |
242 | type_error_exit: |
243 | |
244 | /* Create a string with all expected types for this predefined object */ |
245 | |
246 | acpi_ut_get_expected_return_types(buffer: type_buffer, expected_btypes); |
247 | |
248 | if (!return_object) { |
249 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
250 | info->node_flags, |
251 | "Expected return object of type %s" , |
252 | type_buffer)); |
253 | } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { |
254 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
255 | info->node_flags, |
256 | "Return type mismatch - found %s, expected %s" , |
257 | acpi_ut_get_object_type_name |
258 | (return_object), type_buffer)); |
259 | } else { |
260 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
261 | info->node_flags, |
262 | "Return Package type mismatch at index %u - " |
263 | "found %s, expected %s" , package_index, |
264 | acpi_ut_get_object_type_name |
265 | (return_object), type_buffer)); |
266 | } |
267 | |
268 | return (AE_AML_OPERAND_TYPE); |
269 | } |
270 | |
271 | /******************************************************************************* |
272 | * |
273 | * FUNCTION: acpi_ns_check_reference |
274 | * |
275 | * PARAMETERS: info - Method execution information block |
276 | * return_object - Object returned from the evaluation of a |
277 | * method or object |
278 | * |
279 | * RETURN: Status |
280 | * |
281 | * DESCRIPTION: Check a returned reference object for the correct reference |
282 | * type. The only reference type that can be returned from a |
283 | * predefined method is a named reference. All others are invalid. |
284 | * |
285 | ******************************************************************************/ |
286 | |
287 | static acpi_status |
288 | acpi_ns_check_reference(struct acpi_evaluate_info *info, |
289 | union acpi_operand_object *return_object) |
290 | { |
291 | |
292 | /* |
293 | * Check the reference object for the correct reference type (opcode). |
294 | * The only type of reference that can be converted to a union acpi_object is |
295 | * a reference to a named object (reference class: NAME) |
296 | */ |
297 | if (return_object->reference.class == ACPI_REFCLASS_NAME) { |
298 | return (AE_OK); |
299 | } |
300 | |
301 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, |
302 | "Return type mismatch - unexpected reference object type [%s] %2.2X" , |
303 | acpi_ut_get_reference_name(return_object), |
304 | return_object->reference.class)); |
305 | |
306 | return (AE_AML_OPERAND_TYPE); |
307 | } |
308 | |
309 | /******************************************************************************* |
310 | * |
311 | * FUNCTION: acpi_ns_get_bitmapped_type |
312 | * |
313 | * PARAMETERS: return_object - Object returned from method/obj evaluation |
314 | * |
315 | * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object |
316 | * type is not supported. ACPI_RTYPE_NONE indicates that no |
317 | * object was returned (return_object is NULL). |
318 | * |
319 | * DESCRIPTION: Convert object type into a bitmapped object return type. |
320 | * |
321 | ******************************************************************************/ |
322 | |
323 | static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object) |
324 | { |
325 | u32 return_btype; |
326 | |
327 | if (!return_object) { |
328 | return (ACPI_RTYPE_NONE); |
329 | } |
330 | |
331 | /* Map acpi_object_type to internal bitmapped type */ |
332 | |
333 | switch (return_object->common.type) { |
334 | case ACPI_TYPE_INTEGER: |
335 | |
336 | return_btype = ACPI_RTYPE_INTEGER; |
337 | break; |
338 | |
339 | case ACPI_TYPE_BUFFER: |
340 | |
341 | return_btype = ACPI_RTYPE_BUFFER; |
342 | break; |
343 | |
344 | case ACPI_TYPE_STRING: |
345 | |
346 | return_btype = ACPI_RTYPE_STRING; |
347 | break; |
348 | |
349 | case ACPI_TYPE_PACKAGE: |
350 | |
351 | return_btype = ACPI_RTYPE_PACKAGE; |
352 | break; |
353 | |
354 | case ACPI_TYPE_LOCAL_REFERENCE: |
355 | |
356 | return_btype = ACPI_RTYPE_REFERENCE; |
357 | break; |
358 | |
359 | default: |
360 | |
361 | /* Not one of the supported objects, must be incorrect */ |
362 | |
363 | return_btype = ACPI_RTYPE_ANY; |
364 | break; |
365 | } |
366 | |
367 | return (return_btype); |
368 | } |
369 | |