Branch data Line data Source code
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 - 2020, 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 : 6754 : 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 : 6754 : acpi_status status;
72 : 6754 : const union acpi_predefined_info *predefined;
73 : :
74 : : /* If not a predefined name, we cannot validate the return object */
75 : :
76 : 6754 : predefined = info->predefined;
77 [ + + ]: 6754 : if (!predefined) {
78 : : return (AE_OK);
79 : : }
80 : :
81 : : /*
82 : : * If the method failed or did not actually return an object, we cannot
83 : : * validate the return object
84 : : */
85 [ + - ]: 6721 : if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
86 : : return (AE_OK);
87 : : }
88 : :
89 : : /*
90 : : * Return value validation and possible repair.
91 : : *
92 : : * 1) Don't perform return value validation/repair if this feature
93 : : * has been disabled via a global option.
94 : : *
95 : : * 2) We have a return value, but if one wasn't expected, just exit,
96 : : * this is not a problem. For example, if the "Implicit Return"
97 : : * feature is enabled, methods will always return a value.
98 : : *
99 : : * 3) If the return value can be of any type, then we cannot perform
100 : : * any validation, just exit.
101 : : */
102 [ + - ]: 6721 : if (acpi_gbl_disable_auto_repair ||
103 [ + + + - ]: 6721 : (!predefined->info.expected_btypes) ||
104 : : (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) {
105 : : return (AE_OK);
106 : : }
107 : :
108 : : /*
109 : : * Check that the type of the main return object is what is expected
110 : : * for this predefined name
111 : : */
112 : 6644 : status = acpi_ns_check_object_type(info, return_object_ptr,
113 : : predefined->info.expected_btypes,
114 : : ACPI_NOT_PACKAGE_ELEMENT);
115 [ - + ]: 6644 : if (ACPI_FAILURE(status)) {
116 : 0 : goto exit;
117 : : }
118 : :
119 : : /*
120 : : *
121 : : * 4) If there is no return value and it is optional, just return
122 : : * AE_OK (_WAK).
123 : : */
124 [ - + ]: 6644 : if (!(*return_object_ptr)) {
125 : 0 : goto exit;
126 : : }
127 : :
128 : : /*
129 : : * For returned Package objects, check the type of all sub-objects.
130 : : * Note: Package may have been newly created by call above.
131 : : */
132 [ + + ]: 6644 : if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) {
133 : 55 : info->parent_package = *return_object_ptr;
134 : 55 : status = acpi_ns_check_package(info, return_object_ptr);
135 [ - + ]: 55 : if (ACPI_FAILURE(status)) {
136 : :
137 : : /* We might be able to fix some errors */
138 : :
139 [ # # ]: 0 : if ((status != AE_AML_OPERAND_TYPE) &&
140 : : (status != AE_AML_OPERAND_VALUE)) {
141 : 0 : goto exit;
142 : : }
143 : : }
144 : : }
145 : :
146 : : /*
147 : : * The return object was OK, or it was successfully repaired above.
148 : : * Now make some additional checks such as verifying that package
149 : : * objects are sorted correctly (if required) or buffer objects have
150 : : * the correct data width (bytes vs. dwords). These repairs are
151 : : * performed on a per-name basis, i.e., the code is specific to
152 : : * particular predefined names.
153 : : */
154 : 6644 : status = acpi_ns_complex_repairs(info, node, status, return_object_ptr);
155 : :
156 : 6644 : exit:
157 : : /*
158 : : * If the object validation failed or if we successfully repaired one
159 : : * or more objects, mark the parent node to suppress further warning
160 : : * messages during the next evaluation of the same method/object.
161 : : */
162 [ + - - + ]: 6644 : if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) {
163 : 0 : node->flags |= ANOBJ_EVALUATED;
164 : : }
165 : :
166 : : return (status);
167 : : }
168 : :
169 : : /*******************************************************************************
170 : : *
171 : : * FUNCTION: acpi_ns_check_object_type
172 : : *
173 : : * PARAMETERS: info - Method execution information block
174 : : * return_object_ptr - Pointer to the object returned from the
175 : : * evaluation of a method or object
176 : : * expected_btypes - Bitmap of expected return type(s)
177 : : * package_index - Index of object within parent package (if
178 : : * applicable - ACPI_NOT_PACKAGE_ELEMENT
179 : : * otherwise)
180 : : *
181 : : * RETURN: Status
182 : : *
183 : : * DESCRIPTION: Check the type of the return object against the expected object
184 : : * type(s). Use of Btype allows multiple expected object types.
185 : : *
186 : : ******************************************************************************/
187 : :
188 : : acpi_status
189 : 20856 : acpi_ns_check_object_type(struct acpi_evaluate_info *info,
190 : : union acpi_operand_object **return_object_ptr,
191 : : u32 expected_btypes, u32 package_index)
192 : : {
193 : 20856 : union acpi_operand_object *return_object = *return_object_ptr;
194 : 20856 : acpi_status status = AE_OK;
195 : 20856 : char type_buffer[96]; /* Room for 10 types */
196 : :
197 : : /* A Namespace node should not get here, but make sure */
198 : :
199 [ + - ]: 20856 : if (return_object &&
200 [ - + ]: 20856 : ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
201 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
202 : : info->node_flags,
203 : : "Invalid return type - Found a Namespace node [%4.4s] type %s",
204 : : return_object->node.name.ascii,
205 : : acpi_ut_get_type_name(return_object->node.
206 : : type)));
207 : 0 : return (AE_AML_OPERAND_TYPE);
208 : : }
209 : :
210 : : /*
211 : : * Convert the object type (ACPI_TYPE_xxx) to a bitmapped object type.
212 : : * The bitmapped type allows multiple possible return types.
213 : : *
214 : : * Note, the cases below must handle all of the possible types returned
215 : : * from all of the predefined names (including elements of returned
216 : : * packages)
217 : : */
218 : 20856 : info->return_btype = acpi_ns_get_bitmapped_type(return_object);
219 [ - + ]: 20856 : if (info->return_btype == ACPI_RTYPE_ANY) {
220 : :
221 : : /* Not one of the supported objects, must be incorrect */
222 : 0 : goto type_error_exit;
223 : : }
224 : :
225 : : /* For reference objects, check that the reference type is correct */
226 : :
227 [ + + ]: 20856 : if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) {
228 : 2816 : status = acpi_ns_check_reference(info, return_object);
229 : 2816 : return (status);
230 : : }
231 : :
232 : : /* Attempt simple repair of the returned object if necessary */
233 : :
234 : 18040 : status = acpi_ns_simple_repair(info, expected_btypes,
235 : : package_index, return_object_ptr);
236 [ - + ]: 18040 : if (ACPI_SUCCESS(status)) {
237 : : return (AE_OK); /* Successful repair */
238 : : }
239 : :
240 : 0 : type_error_exit:
241 : :
242 : : /* Create a string with all expected types for this predefined object */
243 : :
244 : 0 : acpi_ut_get_expected_return_types(type_buffer, expected_btypes);
245 : :
246 [ # # ]: 0 : if (!return_object) {
247 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
248 : : info->node_flags,
249 : : "Expected return object of type %s",
250 : : type_buffer));
251 [ # # ]: 0 : } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) {
252 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
253 : : info->node_flags,
254 : : "Return type mismatch - found %s, expected %s",
255 : : acpi_ut_get_object_type_name
256 : : (return_object), type_buffer));
257 : : } else {
258 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
259 : : info->node_flags,
260 : : "Return Package type mismatch at index %u - "
261 : : "found %s, expected %s", package_index,
262 : : acpi_ut_get_object_type_name
263 : : (return_object), type_buffer));
264 : : }
265 : :
266 : : return (AE_AML_OPERAND_TYPE);
267 : : }
268 : :
269 : : /*******************************************************************************
270 : : *
271 : : * FUNCTION: acpi_ns_check_reference
272 : : *
273 : : * PARAMETERS: info - Method execution information block
274 : : * return_object - Object returned from the evaluation of a
275 : : * method or object
276 : : *
277 : : * RETURN: Status
278 : : *
279 : : * DESCRIPTION: Check a returned reference object for the correct reference
280 : : * type. The only reference type that can be returned from a
281 : : * predefined method is a named reference. All others are invalid.
282 : : *
283 : : ******************************************************************************/
284 : :
285 : : static acpi_status
286 : 2816 : acpi_ns_check_reference(struct acpi_evaluate_info *info,
287 : : union acpi_operand_object *return_object)
288 : : {
289 : :
290 : : /*
291 : : * Check the reference object for the correct reference type (opcode).
292 : : * The only type of reference that can be converted to a union acpi_object is
293 : : * a reference to a named object (reference class: NAME)
294 : : */
295 [ - + ]: 2816 : if (return_object->reference.class == ACPI_REFCLASS_NAME) {
296 : : return (AE_OK);
297 : : }
298 : :
299 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags,
300 : : "Return type mismatch - unexpected reference object type [%s] %2.2X",
301 : : acpi_ut_get_reference_name(return_object),
302 : : return_object->reference.class));
303 : :
304 : 0 : return (AE_AML_OPERAND_TYPE);
305 : : }
306 : :
307 : : /*******************************************************************************
308 : : *
309 : : * FUNCTION: acpi_ns_get_bitmapped_type
310 : : *
311 : : * PARAMETERS: return_object - Object returned from method/obj evaluation
312 : : *
313 : : * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object
314 : : * type is not supported. ACPI_RTYPE_NONE indicates that no
315 : : * object was returned (return_object is NULL).
316 : : *
317 : : * DESCRIPTION: Convert object type into a bitmapped object return type.
318 : : *
319 : : ******************************************************************************/
320 : :
321 : 20856 : static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object)
322 : : {
323 : 20856 : u32 return_btype;
324 : :
325 [ + - ]: 20856 : if (!return_object) {
326 : : return (ACPI_RTYPE_NONE);
327 : : }
328 : :
329 : : /* Map acpi_object_type to internal bitmapped type */
330 : :
331 [ - + ]: 20856 : switch (return_object->common.type) {
332 : : case ACPI_TYPE_INTEGER:
333 : :
334 : : return_btype = ACPI_RTYPE_INTEGER;
335 : : break;
336 : :
337 : : case ACPI_TYPE_BUFFER:
338 : :
339 : : return_btype = ACPI_RTYPE_BUFFER;
340 : : break;
341 : :
342 : : case ACPI_TYPE_STRING:
343 : :
344 : : return_btype = ACPI_RTYPE_STRING;
345 : : break;
346 : :
347 : : case ACPI_TYPE_PACKAGE:
348 : :
349 : : return_btype = ACPI_RTYPE_PACKAGE;
350 : : break;
351 : :
352 : : case ACPI_TYPE_LOCAL_REFERENCE:
353 : :
354 : : return_btype = ACPI_RTYPE_REFERENCE;
355 : : break;
356 : :
357 : : default:
358 : :
359 : : /* Not one of the supported objects, must be incorrect */
360 : :
361 : : return_btype = ACPI_RTYPE_ANY;
362 : : break;
363 : : }
364 : :
365 : : return (return_btype);
366 : : }
|