aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-11-12 22:19:24 -0500
committerLen Brown <len.brown@intel.com>2008-12-29 22:38:39 -0500
commiteeb4437e63c39ce19cf9b2de36a1dddbf12910c4 (patch)
treef8a03de090080a3a781a927ca13253774aebdfe7
parenta647b5c34047560d7efe7e53e756c6692ce67dc7 (diff)
ACPICA: Consolidate method arg count validation code
Merge the code that validates control method argument counts into the predefined validation module. Eliminates possible multiple warnings for incorrect counts. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/namespace/nseval.c69
-rw-r--r--drivers/acpi/namespace/nspredef.c106
-rw-r--r--include/acpi/acnamesp.h3
3 files changed, 104 insertions, 74 deletions
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 738a4517b7c1..b95bfbbf5617 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -89,6 +89,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
89 /* Initialize the return value to an invalid object */ 89 /* Initialize the return value to an invalid object */
90 90
91 info->return_object = NULL; 91 info->return_object = NULL;
92 info->param_count = 0;
92 93
93 /* 94 /*
94 * Get the actual namespace node for the target object. Handles these cases: 95 * Get the actual namespace node for the target object. Handles these cases:
@@ -141,41 +142,17 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
141 return_ACPI_STATUS(AE_NULL_OBJECT); 142 return_ACPI_STATUS(AE_NULL_OBJECT);
142 } 143 }
143 144
144 /* 145 /* Count the number of arguments being passed to the method */
145 * Calculate the number of arguments being passed to the method
146 */
147 146
148 info->param_count = 0;
149 if (info->parameters) { 147 if (info->parameters) {
150 while (info->parameters[info->param_count]) 148 while (info->parameters[info->param_count]) {
149 if (info->param_count > ACPI_METHOD_MAX_ARG) {
150 return_ACPI_STATUS(AE_LIMIT);
151 }
151 info->param_count++; 152 info->param_count++;
153 }
152 } 154 }
153 155
154 /*
155 * Warning if too few or too many arguments have been passed by the
156 * caller. We don't want to abort here with an error because an
157 * incorrect number of arguments may not cause the method to fail.
158 * However, the method will fail if there are too few arguments passed
159 * and the method attempts to use one of the missing ones.
160 */
161
162 if (info->param_count < info->obj_desc->method.param_count) {
163 ACPI_WARNING((AE_INFO,
164 "Insufficient arguments - "
165 "method [%4.4s] needs %d, found %d",
166 acpi_ut_get_node_name(info->resolved_node),
167 info->obj_desc->method.param_count,
168 info->param_count));
169 } else if (info->param_count >
170 info->obj_desc->method.param_count) {
171 ACPI_WARNING((AE_INFO,
172 "Excess arguments - "
173 "method [%4.4s] needs %d, found %d",
174 acpi_ut_get_node_name(info->
175 resolved_node),
176 info->obj_desc->method.param_count,
177 info->param_count));
178 }
179 156
180 ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", 157 ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
181 ACPI_LV_INFO, _COMPONENT); 158 ACPI_LV_INFO, _COMPONENT);
@@ -264,31 +241,13 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
264 } 241 }
265 } 242 }
266 243
267 /* Validation of return values for ACPI-predefined methods and objects */ 244 /*
268 245 * Check input argument count against the ASL-defined count for a method.
269 if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) { 246 * Also check predefined names: argument count and return value against
270 /* 247 * the ACPI specification. Some incorrect return value types are repaired.
271 * If this is the first evaluation, check the return value. This 248 */
272 * ensures that any warnings will only be emitted during the very 249 (void)acpi_ns_check_predefined_names(node, info->param_count,
273 * first evaluation of the object. 250 status, &info->return_object);
274 */
275 if (!(node->flags & ANOBJ_EVALUATED)) {
276 /*
277 * Check for a predefined ACPI name. If found, validate the
278 * returned object.
279 *
280 * Note: Ignore return status for now, emit warnings if there are
281 * problems with the returned object. May change later to abort
282 * the method on invalid return object.
283 */
284 (void)acpi_ns_check_predefined_names(node,
285 &info->return_object);
286 }
287
288 /* Mark the node as having been evaluated */
289
290 node->flags |= ANOBJ_EVALUATED;
291 }
292 251
293 /* Check if there is a return value that must be dealt with */ 252 /* Check if there is a return value that must be dealt with */
294 253
diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/namespace/nspredef.c
index 3df17522117f..8d354baaed53 100644
--- a/drivers/acpi/namespace/nspredef.c
+++ b/drivers/acpi/namespace/nspredef.c
@@ -124,6 +124,8 @@ static const char *acpi_rtype_names[] = {
124 124
125acpi_status 125acpi_status
126acpi_ns_check_predefined_names(struct acpi_namespace_node *node, 126acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
127 u32 user_param_count,
128 acpi_status return_status,
127 union acpi_operand_object **return_object_ptr) 129 union acpi_operand_object **return_object_ptr)
128{ 130{
129 union acpi_operand_object *return_object = *return_object_ptr; 131 union acpi_operand_object *return_object = *return_object_ptr;
@@ -134,12 +136,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
134 /* Match the name for this method/object against the predefined list */ 136 /* Match the name for this method/object against the predefined list */
135 137
136 predefined = acpi_ns_check_for_predefined_name(node); 138 predefined = acpi_ns_check_for_predefined_name(node);
137 if (!predefined) {
138
139 /* Name was not one of the predefined names */
140
141 return (AE_OK);
142 }
143 139
144 /* Get the full pathname to the object, for use in error messages */ 140 /* Get the full pathname to the object, for use in error messages */
145 141
@@ -149,10 +145,37 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
149 } 145 }
150 146
151 /* 147 /*
152 * Check that the parameter count for this method is in accordance 148 * Check that the parameter count for this method matches the ASL
153 * with the ACPI specification. 149 * definition. For predefined names, ensure that both the caller and
150 * the method itself are in accordance with the ACPI specification.
154 */ 151 */
155 acpi_ns_check_parameter_count(pathname, node, predefined); 152 acpi_ns_check_parameter_count(pathname, node, user_param_count,
153 predefined);
154
155 /* If not a predefined name, we cannot validate the return object */
156
157 if (!predefined) {
158 goto exit;
159 }
160
161 /* If the method failed, we cannot validate the return object */
162
163 if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
164 goto exit;
165 }
166
167 /*
168 * Only validate the return value on the first successful evaluation of
169 * the method. This ensures that any warnings will only be emitted during
170 * the very first evaluation of the method/object.
171 */
172 if (node->flags & ANOBJ_EVALUATED) {
173 goto exit;
174 }
175
176 /* Mark the node as having been successfully evaluated */
177
178 node->flags |= ANOBJ_EVALUATED;
156 179
157 /* 180 /*
158 * If there is no return value, check if we require a return value for 181 * If there is no return value, check if we require a return value for
@@ -177,7 +200,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
177 * We have a return value, but if one wasn't expected, just exit, this is 200 * We have a return value, but if one wasn't expected, just exit, this is
178 * not a problem 201 * not a problem
179 * 202 *
180 * For example, if "Implicit return value" is enabled, methods will 203 * For example, if the "Implicit Return" feature is enabled, methods will
181 * always return a value 204 * always return a value
182 */ 205 */
183 if (!predefined->info.expected_btypes) { 206 if (!predefined->info.expected_btypes) {
@@ -204,7 +227,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
204 } 227 }
205 228
206 exit: 229 exit:
207 if (pathname) { 230 if (pathname != predefined->info.name) {
208 ACPI_FREE(pathname); 231 ACPI_FREE(pathname);
209 } 232 }
210 233
@@ -217,6 +240,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
217 * 240 *
218 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 241 * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
219 * Node - Namespace node for the method/object 242 * Node - Namespace node for the method/object
243 * user_param_count - Number of args passed in by the caller
220 * Predefined - Pointer to entry in predefined name table 244 * Predefined - Pointer to entry in predefined name table
221 * 245 *
222 * RETURN: None 246 * RETURN: None
@@ -230,32 +254,76 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
230void 254void
231acpi_ns_check_parameter_count(char *pathname, 255acpi_ns_check_parameter_count(char *pathname,
232 struct acpi_namespace_node *node, 256 struct acpi_namespace_node *node,
257 u32 user_param_count,
233 const union acpi_predefined_info *predefined) 258 const union acpi_predefined_info *predefined)
234{ 259{
235 u32 param_count; 260 u32 param_count;
236 u32 required_params_current; 261 u32 required_params_current;
237 u32 required_params_old; 262 u32 required_params_old;
238 263
239 /* 264 /* Methods have 0-7 parameters. All other types have zero. */
240 * Check that the ASL-defined parameter count is what is expected for 265
241 * this predefined name.
242 *
243 * Methods have 0-7 parameters. All other types have zero.
244 */
245 param_count = 0; 266 param_count = 0;
246 if (node->type == ACPI_TYPE_METHOD) { 267 if (node->type == ACPI_TYPE_METHOD) {
247 param_count = node->object->method.param_count; 268 param_count = node->object->method.param_count;
248 } 269 }
249 270
250 /* Validate parameter count - allow two different legal counts (_SCP) */ 271 /* Argument count check for non-predefined methods/objects */
272
273 if (!predefined) {
274 /*
275 * Warning if too few or too many arguments have been passed by the
276 * caller. An incorrect number of arguments may not cause the method
277 * to fail. However, the method will fail if there are too few
278 * arguments and the method attempts to use one of the missing ones.
279 */
280 if (user_param_count < param_count) {
281 ACPI_WARNING((AE_INFO,
282 "%s: Insufficient arguments - needs %d, found %d",
283 pathname, param_count, user_param_count));
284 } else if (user_param_count > param_count) {
285 ACPI_WARNING((AE_INFO,
286 "%s: Excess arguments - needs %d, found %d",
287 pathname, param_count, user_param_count));
288 }
289 return;
290 }
291
292 /* Allow two different legal argument counts (_SCP, etc.) */
251 293
252 required_params_current = predefined->info.param_count & 0x0F; 294 required_params_current = predefined->info.param_count & 0x0F;
253 required_params_old = predefined->info.param_count >> 4; 295 required_params_old = predefined->info.param_count >> 4;
254 296
297 if (user_param_count != ACPI_UINT32_MAX) {
298
299 /* Validate the user-supplied parameter count */
300
301 if ((user_param_count != required_params_current) &&
302 (user_param_count != required_params_old)) {
303 ACPI_WARNING((AE_INFO,
304 "%s: Parameter count mismatch - caller passed %d, ACPI requires %d",
305 pathname, user_param_count,
306 required_params_current));
307 }
308 }
309
310 /*
311 * Only validate the argument count on the first successful evaluation of
312 * the method. This ensures that any warnings will only be emitted during
313 * the very first evaluation of the method/object.
314 */
315 if (node->flags & ANOBJ_EVALUATED) {
316 return;
317 }
318
319 /*
320 * Check that the ASL-defined parameter count is what is expected for
321 * this predefined name.
322 */
255 if ((param_count != required_params_current) && 323 if ((param_count != required_params_current) &&
256 (param_count != required_params_old)) { 324 (param_count != required_params_old)) {
257 ACPI_WARNING((AE_INFO, 325 ACPI_WARNING((AE_INFO,
258 "%s: Parameter count mismatch - ASL declared %d, expected %d", 326 "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d",
259 pathname, param_count, required_params_current)); 327 pathname, param_count, required_params_current));
260 } 328 }
261} 329}
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index db1e29052077..46cb5b46d280 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -182,6 +182,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
182 */ 182 */
183acpi_status 183acpi_status
184acpi_ns_check_predefined_names(struct acpi_namespace_node *node, 184acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
185 u32 user_param_count,
186 acpi_status return_status,
185 union acpi_operand_object **return_object); 187 union acpi_operand_object **return_object);
186 188
187const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct 189const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
@@ -191,6 +193,7 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
191void 193void
192acpi_ns_check_parameter_count(char *pathname, 194acpi_ns_check_parameter_count(char *pathname,
193 struct acpi_namespace_node *node, 195 struct acpi_namespace_node *node,
196 u32 user_param_count,
194 const union acpi_predefined_info *info); 197 const union acpi_predefined_info *info);
195 198
196/* 199/*