diff options
author | Bob Moore <robert.moore@intel.com> | 2013-05-29 22:00:01 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-01 15:54:30 -0400 |
commit | 29a241cc02110b8b2259fd72719b8cadc03909be (patch) | |
tree | a96c10dd22a35479dc2e1ef140f7d90a442f9c03 /drivers/acpi/acpica/nspredef.c | |
parent | e1405ca5ebf1068a0d62afd2fec8f0354038147a (diff) |
ACPICA: Add argument typechecking for all predefined ACPI names
Fully implements typechecking on all incoming arguments for all
predefined names. This ensures that ACPI-related drivers are
passing the correct number of arguments, each of the correct
object type.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Acked-by: Len Brown <len.brown@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/nspredef.c')
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 201 |
1 files changed, 43 insertions, 158 deletions
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 8a52916148cb..7ab7ddbe3ded 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -61,28 +61,29 @@ ACPI_MODULE_NAME("nspredef") | |||
61 | * There are several areas that are validated: | 61 | * There are several areas that are validated: |
62 | * | 62 | * |
63 | * 1) The number of input arguments as defined by the method/object in the | 63 | * 1) The number of input arguments as defined by the method/object in the |
64 | * ASL is validated against the ACPI specification. | 64 | * ASL is validated against the ACPI specification. |
65 | * 2) The type of the return object (if any) is validated against the ACPI | 65 | * 2) The type of the return object (if any) is validated against the ACPI |
66 | * specification. | 66 | * specification. |
67 | * 3) For returned package objects, the count of package elements is | 67 | * 3) For returned package objects, the count of package elements is |
68 | * validated, as well as the type of each package element. Nested | 68 | * validated, as well as the type of each package element. Nested |
69 | * packages are supported. | 69 | * packages are supported. |
70 | * | 70 | * |
71 | * For any problems found, a warning message is issued. | 71 | * For any problems found, a warning message is issued. |
72 | * | 72 | * |
73 | ******************************************************************************/ | 73 | ******************************************************************************/ |
74 | /* Local prototypes */ | 74 | /* Local prototypes */ |
75 | static acpi_status | 75 | static acpi_status |
76 | acpi_ns_check_reference(struct acpi_predefined_data *data, | 76 | acpi_ns_check_reference(struct acpi_evaluate_info *info, |
77 | union acpi_operand_object *return_object); | 77 | union acpi_operand_object *return_object); |
78 | 78 | ||
79 | static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); | 79 | static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); |
80 | 80 | ||
81 | /******************************************************************************* | 81 | /******************************************************************************* |
82 | * | 82 | * |
83 | * FUNCTION: acpi_ns_check_predefined_names | 83 | * FUNCTION: acpi_ns_check_return_value |
84 | * | 84 | * |
85 | * PARAMETERS: node - Namespace node for the method/object | 85 | * PARAMETERS: node - Namespace node for the method/object |
86 | * info - Method execution information block | ||
86 | * user_param_count - Number of parameters actually passed | 87 | * user_param_count - Number of parameters actually passed |
87 | * return_status - Status from the object evaluation | 88 | * return_status - Status from the object evaluation |
88 | * return_object_ptr - Pointer to the object returned from the | 89 | * return_object_ptr - Pointer to the object returned from the |
@@ -90,44 +91,28 @@ static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); | |||
90 | * | 91 | * |
91 | * RETURN: Status | 92 | * RETURN: Status |
92 | * | 93 | * |
93 | * DESCRIPTION: Check an ACPI name for a match in the predefined name list. | 94 | * DESCRIPTION: Check the value returned from a predefined name. |
94 | * | 95 | * |
95 | ******************************************************************************/ | 96 | ******************************************************************************/ |
96 | 97 | ||
97 | acpi_status | 98 | acpi_status |
98 | acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | 99 | acpi_ns_check_return_value(struct acpi_namespace_node *node, |
99 | u32 user_param_count, | 100 | struct acpi_evaluate_info *info, |
100 | acpi_status return_status, | 101 | u32 user_param_count, |
101 | union acpi_operand_object **return_object_ptr) | 102 | acpi_status return_status, |
103 | union acpi_operand_object **return_object_ptr) | ||
102 | { | 104 | { |
103 | acpi_status status = AE_OK; | 105 | acpi_status status; |
104 | const union acpi_predefined_info *predefined; | 106 | const union acpi_predefined_info *predefined; |
105 | char *pathname; | 107 | char *pathname; |
106 | struct acpi_predefined_data *data; | ||
107 | |||
108 | /* Match the name for this method/object against the predefined list */ | ||
109 | |||
110 | predefined = acpi_ut_match_predefined_method(node->name.ascii); | ||
111 | 108 | ||
112 | /* Get the full pathname to the object, for use in warning messages */ | 109 | predefined = info->predefined; |
113 | 110 | pathname = info->full_pathname; | |
114 | pathname = acpi_ns_get_external_pathname(node); | ||
115 | if (!pathname) { | ||
116 | return (AE_OK); /* Could not get pathname, ignore */ | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Check that the parameter count for this method matches the ASL | ||
121 | * definition. For predefined names, ensure that both the caller and | ||
122 | * the method itself are in accordance with the ACPI specification. | ||
123 | */ | ||
124 | acpi_ns_check_parameter_count(pathname, node, user_param_count, | ||
125 | predefined); | ||
126 | 111 | ||
127 | /* If not a predefined name, we cannot validate the return object */ | 112 | /* If not a predefined name, we cannot validate the return object */ |
128 | 113 | ||
129 | if (!predefined) { | 114 | if (!predefined) { |
130 | goto cleanup; | 115 | return (AE_OK); |
131 | } | 116 | } |
132 | 117 | ||
133 | /* | 118 | /* |
@@ -135,7 +120,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
135 | * validate the return object | 120 | * validate the return object |
136 | */ | 121 | */ |
137 | if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { | 122 | if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { |
138 | goto cleanup; | 123 | return (AE_OK); |
139 | } | 124 | } |
140 | 125 | ||
141 | /* | 126 | /* |
@@ -154,25 +139,14 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
154 | if (acpi_gbl_disable_auto_repair || | 139 | if (acpi_gbl_disable_auto_repair || |
155 | (!predefined->info.expected_btypes) || | 140 | (!predefined->info.expected_btypes) || |
156 | (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { | 141 | (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { |
157 | goto cleanup; | 142 | return (AE_OK); |
158 | } | ||
159 | |||
160 | /* Create the parameter data block for object validation */ | ||
161 | |||
162 | data = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_predefined_data)); | ||
163 | if (!data) { | ||
164 | goto cleanup; | ||
165 | } | 143 | } |
166 | data->predefined = predefined; | ||
167 | data->node = node; | ||
168 | data->node_flags = node->flags; | ||
169 | data->pathname = pathname; | ||
170 | 144 | ||
171 | /* | 145 | /* |
172 | * Check that the type of the main return object is what is expected | 146 | * Check that the type of the main return object is what is expected |
173 | * for this predefined name | 147 | * for this predefined name |
174 | */ | 148 | */ |
175 | status = acpi_ns_check_object_type(data, return_object_ptr, | 149 | status = acpi_ns_check_object_type(info, return_object_ptr, |
176 | predefined->info.expected_btypes, | 150 | predefined->info.expected_btypes, |
177 | ACPI_NOT_PACKAGE_ELEMENT); | 151 | ACPI_NOT_PACKAGE_ELEMENT); |
178 | if (ACPI_FAILURE(status)) { | 152 | if (ACPI_FAILURE(status)) { |
@@ -184,8 +158,8 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
184 | * Note: Package may have been newly created by call above. | 158 | * Note: Package may have been newly created by call above. |
185 | */ | 159 | */ |
186 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { | 160 | if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { |
187 | data->parent_package = *return_object_ptr; | 161 | info->parent_package = *return_object_ptr; |
188 | status = acpi_ns_check_package(data, return_object_ptr); | 162 | status = acpi_ns_check_package(info, return_object_ptr); |
189 | if (ACPI_FAILURE(status)) { | 163 | if (ACPI_FAILURE(status)) { |
190 | goto exit; | 164 | goto exit; |
191 | } | 165 | } |
@@ -199,7 +173,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
199 | * performed on a per-name basis, i.e., the code is specific to | 173 | * performed on a per-name basis, i.e., the code is specific to |
200 | * particular predefined names. | 174 | * particular predefined names. |
201 | */ | 175 | */ |
202 | status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); | 176 | status = acpi_ns_complex_repairs(info, node, status, return_object_ptr); |
203 | 177 | ||
204 | exit: | 178 | exit: |
205 | /* | 179 | /* |
@@ -207,112 +181,18 @@ exit: | |||
207 | * or more objects, mark the parent node to suppress further warning | 181 | * or more objects, mark the parent node to suppress further warning |
208 | * messages during the next evaluation of the same method/object. | 182 | * messages during the next evaluation of the same method/object. |
209 | */ | 183 | */ |
210 | if (ACPI_FAILURE(status) || (data->flags & ACPI_OBJECT_REPAIRED)) { | 184 | if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { |
211 | node->flags |= ANOBJ_EVALUATED; | 185 | node->flags |= ANOBJ_EVALUATED; |
212 | } | 186 | } |
213 | ACPI_FREE(data); | ||
214 | 187 | ||
215 | cleanup: | ||
216 | ACPI_FREE(pathname); | ||
217 | return (status); | 188 | return (status); |
218 | } | 189 | } |
219 | 190 | ||
220 | /******************************************************************************* | 191 | /******************************************************************************* |
221 | * | 192 | * |
222 | * FUNCTION: acpi_ns_check_parameter_count | ||
223 | * | ||
224 | * PARAMETERS: pathname - Full pathname to the node (for error msgs) | ||
225 | * node - Namespace node for the method/object | ||
226 | * user_param_count - Number of args passed in by the caller | ||
227 | * predefined - Pointer to entry in predefined name table | ||
228 | * | ||
229 | * RETURN: None | ||
230 | * | ||
231 | * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a | ||
232 | * predefined name is what is expected (i.e., what is defined in | ||
233 | * the ACPI specification for this predefined name.) | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | void | ||
238 | acpi_ns_check_parameter_count(char *pathname, | ||
239 | struct acpi_namespace_node *node, | ||
240 | u32 user_param_count, | ||
241 | const union acpi_predefined_info *predefined) | ||
242 | { | ||
243 | u32 param_count; | ||
244 | u32 required_params_current; | ||
245 | u32 required_params_old; | ||
246 | |||
247 | /* Methods have 0-7 parameters. All other types have zero. */ | ||
248 | |||
249 | param_count = 0; | ||
250 | if (node->type == ACPI_TYPE_METHOD) { | ||
251 | param_count = node->object->method.param_count; | ||
252 | } | ||
253 | |||
254 | if (!predefined) { | ||
255 | /* | ||
256 | * Check the parameter count for non-predefined methods/objects. | ||
257 | * | ||
258 | * Warning if too few or too many arguments have been passed by the | ||
259 | * caller. An incorrect number of arguments may not cause the method | ||
260 | * to fail. However, the method will fail if there are too few | ||
261 | * arguments and the method attempts to use one of the missing ones. | ||
262 | */ | ||
263 | if (user_param_count < param_count) { | ||
264 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, | ||
265 | ACPI_WARN_ALWAYS, | ||
266 | "Insufficient arguments - needs %u, found %u", | ||
267 | param_count, user_param_count)); | ||
268 | } else if (user_param_count > param_count) { | ||
269 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, | ||
270 | ACPI_WARN_ALWAYS, | ||
271 | "Excess arguments - needs %u, found %u", | ||
272 | param_count, user_param_count)); | ||
273 | } | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Validate the user-supplied parameter count. | ||
279 | * Allow two different legal argument counts (_SCP, etc.) | ||
280 | */ | ||
281 | required_params_current = | ||
282 | predefined->info.argument_list & METHOD_ARG_MASK; | ||
283 | required_params_old = | ||
284 | predefined->info.argument_list >> METHOD_ARG_BIT_WIDTH; | ||
285 | |||
286 | if (user_param_count != ACPI_UINT32_MAX) { | ||
287 | if ((user_param_count != required_params_current) && | ||
288 | (user_param_count != required_params_old)) { | ||
289 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, | ||
290 | ACPI_WARN_ALWAYS, | ||
291 | "Parameter count mismatch - " | ||
292 | "caller passed %u, ACPI requires %u", | ||
293 | user_param_count, | ||
294 | required_params_current)); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Check that the ASL-defined parameter count is what is expected for | ||
300 | * this predefined name (parameter count as defined by the ACPI | ||
301 | * specification) | ||
302 | */ | ||
303 | if ((param_count != required_params_current) && | ||
304 | (param_count != required_params_old)) { | ||
305 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, node->flags, | ||
306 | "Parameter count mismatch - ASL declared %u, ACPI requires %u", | ||
307 | param_count, required_params_current)); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /******************************************************************************* | ||
312 | * | ||
313 | * FUNCTION: acpi_ns_check_object_type | 193 | * FUNCTION: acpi_ns_check_object_type |
314 | * | 194 | * |
315 | * PARAMETERS: data - Pointer to validation data structure | 195 | * PARAMETERS: info - Method execution information block |
316 | * return_object_ptr - Pointer to the object returned from the | 196 | * return_object_ptr - Pointer to the object returned from the |
317 | * evaluation of a method or object | 197 | * evaluation of a method or object |
318 | * expected_btypes - Bitmap of expected return type(s) | 198 | * expected_btypes - Bitmap of expected return type(s) |
@@ -328,7 +208,7 @@ acpi_ns_check_parameter_count(char *pathname, | |||
328 | ******************************************************************************/ | 208 | ******************************************************************************/ |
329 | 209 | ||
330 | acpi_status | 210 | acpi_status |
331 | acpi_ns_check_object_type(struct acpi_predefined_data *data, | 211 | acpi_ns_check_object_type(struct acpi_evaluate_info *info, |
332 | union acpi_operand_object **return_object_ptr, | 212 | union acpi_operand_object **return_object_ptr, |
333 | u32 expected_btypes, u32 package_index) | 213 | u32 expected_btypes, u32 package_index) |
334 | { | 214 | { |
@@ -340,7 +220,8 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
340 | 220 | ||
341 | if (return_object && | 221 | if (return_object && |
342 | ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { | 222 | ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { |
343 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | 223 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
224 | info->node_flags, | ||
344 | "Invalid return type - Found a Namespace node [%4.4s] type %s", | 225 | "Invalid return type - Found a Namespace node [%4.4s] type %s", |
345 | return_object->node.name.ascii, | 226 | return_object->node.name.ascii, |
346 | acpi_ut_get_type_name(return_object->node. | 227 | acpi_ut_get_type_name(return_object->node. |
@@ -356,8 +237,8 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
356 | * from all of the predefined names (including elements of returned | 237 | * from all of the predefined names (including elements of returned |
357 | * packages) | 238 | * packages) |
358 | */ | 239 | */ |
359 | data->return_btype = acpi_ns_get_bitmapped_type(return_object); | 240 | info->return_btype = acpi_ns_get_bitmapped_type(return_object); |
360 | if (data->return_btype == ACPI_RTYPE_ANY) { | 241 | if (info->return_btype == ACPI_RTYPE_ANY) { |
361 | 242 | ||
362 | /* Not one of the supported objects, must be incorrect */ | 243 | /* Not one of the supported objects, must be incorrect */ |
363 | goto type_error_exit; | 244 | goto type_error_exit; |
@@ -365,16 +246,18 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
365 | 246 | ||
366 | /* For reference objects, check that the reference type is correct */ | 247 | /* For reference objects, check that the reference type is correct */ |
367 | 248 | ||
368 | if ((data->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { | 249 | if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { |
369 | status = acpi_ns_check_reference(data, return_object); | 250 | status = acpi_ns_check_reference(info, return_object); |
370 | return (status); | 251 | return (status); |
371 | } | 252 | } |
372 | 253 | ||
373 | /* Attempt simple repair of the returned object if necessary */ | 254 | /* Attempt simple repair of the returned object if necessary */ |
374 | 255 | ||
375 | status = acpi_ns_simple_repair(data, expected_btypes, | 256 | status = acpi_ns_simple_repair(info, expected_btypes, |
376 | package_index, return_object_ptr); | 257 | package_index, return_object_ptr); |
377 | return (status); | 258 | if (ACPI_SUCCESS(status)) { |
259 | return (AE_OK); /* Successful repair */ | ||
260 | } | ||
378 | 261 | ||
379 | type_error_exit: | 262 | type_error_exit: |
380 | 263 | ||
@@ -383,12 +266,14 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
383 | acpi_ut_get_expected_return_types(type_buffer, expected_btypes); | 266 | acpi_ut_get_expected_return_types(type_buffer, expected_btypes); |
384 | 267 | ||
385 | if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { | 268 | if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { |
386 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | 269 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
270 | info->node_flags, | ||
387 | "Return type mismatch - found %s, expected %s", | 271 | "Return type mismatch - found %s, expected %s", |
388 | acpi_ut_get_object_type_name | 272 | acpi_ut_get_object_type_name |
389 | (return_object), type_buffer)); | 273 | (return_object), type_buffer)); |
390 | } else { | 274 | } else { |
391 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | 275 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, |
276 | info->node_flags, | ||
392 | "Return Package type mismatch at index %u - " | 277 | "Return Package type mismatch at index %u - " |
393 | "found %s, expected %s", package_index, | 278 | "found %s, expected %s", package_index, |
394 | acpi_ut_get_object_type_name | 279 | acpi_ut_get_object_type_name |
@@ -402,7 +287,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
402 | * | 287 | * |
403 | * FUNCTION: acpi_ns_check_reference | 288 | * FUNCTION: acpi_ns_check_reference |
404 | * | 289 | * |
405 | * PARAMETERS: data - Pointer to validation data structure | 290 | * PARAMETERS: info - Method execution information block |
406 | * return_object - Object returned from the evaluation of a | 291 | * return_object - Object returned from the evaluation of a |
407 | * method or object | 292 | * method or object |
408 | * | 293 | * |
@@ -415,7 +300,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, | |||
415 | ******************************************************************************/ | 300 | ******************************************************************************/ |
416 | 301 | ||
417 | static acpi_status | 302 | static acpi_status |
418 | acpi_ns_check_reference(struct acpi_predefined_data *data, | 303 | acpi_ns_check_reference(struct acpi_evaluate_info *info, |
419 | union acpi_operand_object *return_object) | 304 | union acpi_operand_object *return_object) |
420 | { | 305 | { |
421 | 306 | ||
@@ -428,7 +313,7 @@ acpi_ns_check_reference(struct acpi_predefined_data *data, | |||
428 | return (AE_OK); | 313 | return (AE_OK); |
429 | } | 314 | } |
430 | 315 | ||
431 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | 316 | ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, |
432 | "Return type mismatch - unexpected reference object type [%s] %2.2X", | 317 | "Return type mismatch - unexpected reference object type [%s] %2.2X", |
433 | acpi_ut_get_reference_name(return_object), | 318 | acpi_ut_get_reference_name(return_object), |
434 | return_object->reference.class)); | 319 | return_object->reference.class)); |