Skip to content

Commit

Permalink
ACPICA: Consolidate method arg count validation code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bob Moore authored and Len Brown committed Dec 30, 2008
1 parent a647b5c commit eeb4437
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 74 deletions.
69 changes: 14 additions & 55 deletions drivers/acpi/namespace/nseval.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
/* Initialize the return value to an invalid object */

info->return_object = NULL;
info->param_count = 0;

/*
* Get the actual namespace node for the target object. Handles these cases:
Expand Down Expand Up @@ -141,41 +142,17 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
return_ACPI_STATUS(AE_NULL_OBJECT);
}

/*
* Calculate the number of arguments being passed to the method
*/
/* Count the number of arguments being passed to the method */

info->param_count = 0;
if (info->parameters) {
while (info->parameters[info->param_count])
while (info->parameters[info->param_count]) {
if (info->param_count > ACPI_METHOD_MAX_ARG) {
return_ACPI_STATUS(AE_LIMIT);
}
info->param_count++;
}
}

/*
* Warning if too few or too many arguments have been passed by the
* caller. We don't want to abort here with an error because an
* incorrect number of arguments may not cause the method to fail.
* However, the method will fail if there are too few arguments passed
* and the method attempts to use one of the missing ones.
*/

if (info->param_count < info->obj_desc->method.param_count) {
ACPI_WARNING((AE_INFO,
"Insufficient arguments - "
"method [%4.4s] needs %d, found %d",
acpi_ut_get_node_name(info->resolved_node),
info->obj_desc->method.param_count,
info->param_count));
} else if (info->param_count >
info->obj_desc->method.param_count) {
ACPI_WARNING((AE_INFO,
"Excess arguments - "
"method [%4.4s] needs %d, found %d",
acpi_ut_get_node_name(info->
resolved_node),
info->obj_desc->method.param_count,
info->param_count));
}

ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
ACPI_LV_INFO, _COMPONENT);
Expand Down Expand Up @@ -264,31 +241,13 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
}
}

/* Validation of return values for ACPI-predefined methods and objects */

if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
/*
* If this is the first evaluation, check the return value. This
* ensures that any warnings will only be emitted during the very
* first evaluation of the object.
*/
if (!(node->flags & ANOBJ_EVALUATED)) {
/*
* Check for a predefined ACPI name. If found, validate the
* returned object.
*
* Note: Ignore return status for now, emit warnings if there are
* problems with the returned object. May change later to abort
* the method on invalid return object.
*/
(void)acpi_ns_check_predefined_names(node,
&info->return_object);
}

/* Mark the node as having been evaluated */

node->flags |= ANOBJ_EVALUATED;
}
/*
* Check input argument count against the ASL-defined count for a method.
* Also check predefined names: argument count and return value against
* the ACPI specification. Some incorrect return value types are repaired.
*/
(void)acpi_ns_check_predefined_names(node, info->param_count,
status, &info->return_object);

/* Check if there is a return value that must be dealt with */

Expand Down
106 changes: 87 additions & 19 deletions drivers/acpi/namespace/nspredef.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ static const char *acpi_rtype_names[] = {

acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
u32 user_param_count,
acpi_status return_status,
union acpi_operand_object **return_object_ptr)
{
union acpi_operand_object *return_object = *return_object_ptr;
Expand All @@ -134,12 +136,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
/* Match the name for this method/object against the predefined list */

predefined = acpi_ns_check_for_predefined_name(node);
if (!predefined) {

/* Name was not one of the predefined names */

return (AE_OK);
}

/* Get the full pathname to the object, for use in error messages */

Expand All @@ -149,10 +145,37 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
}

/*
* Check that the parameter count for this method is in accordance
* with the ACPI specification.
* Check that the parameter count for this method matches the ASL
* definition. For predefined names, ensure that both the caller and
* the method itself are in accordance with the ACPI specification.
*/
acpi_ns_check_parameter_count(pathname, node, predefined);
acpi_ns_check_parameter_count(pathname, node, user_param_count,
predefined);

/* If not a predefined name, we cannot validate the return object */

if (!predefined) {
goto exit;
}

/* If the method failed, we cannot validate the return object */

if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
goto exit;
}

/*
* Only validate the return value on the first successful evaluation of
* the method. This ensures that any warnings will only be emitted during
* the very first evaluation of the method/object.
*/
if (node->flags & ANOBJ_EVALUATED) {
goto exit;
}

/* Mark the node as having been successfully evaluated */

node->flags |= ANOBJ_EVALUATED;

/*
* If there is no return value, check if we require a return value for
Expand All @@ -177,7 +200,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
* We have a return value, but if one wasn't expected, just exit, this is
* not a problem
*
* For example, if "Implicit return value" is enabled, methods will
* For example, if the "Implicit Return" feature is enabled, methods will
* always return a value
*/
if (!predefined->info.expected_btypes) {
Expand All @@ -204,7 +227,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
}

exit:
if (pathname) {
if (pathname != predefined->info.name) {
ACPI_FREE(pathname);
}

Expand All @@ -217,6 +240,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
*
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
* Node - Namespace node for the method/object
* user_param_count - Number of args passed in by the caller
* Predefined - Pointer to entry in predefined name table
*
* RETURN: None
Expand All @@ -230,32 +254,76 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
void
acpi_ns_check_parameter_count(char *pathname,
struct acpi_namespace_node *node,
u32 user_param_count,
const union acpi_predefined_info *predefined)
{
u32 param_count;
u32 required_params_current;
u32 required_params_old;

/*
* Check that the ASL-defined parameter count is what is expected for
* this predefined name.
*
* Methods have 0-7 parameters. All other types have zero.
*/
/* Methods have 0-7 parameters. All other types have zero. */

param_count = 0;
if (node->type == ACPI_TYPE_METHOD) {
param_count = node->object->method.param_count;
}

/* Validate parameter count - allow two different legal counts (_SCP) */
/* Argument count check for non-predefined methods/objects */

if (!predefined) {
/*
* Warning if too few or too many arguments have been passed by the
* caller. An incorrect number of arguments may not cause the method
* to fail. However, the method will fail if there are too few
* arguments and the method attempts to use one of the missing ones.
*/
if (user_param_count < param_count) {
ACPI_WARNING((AE_INFO,
"%s: Insufficient arguments - needs %d, found %d",
pathname, param_count, user_param_count));
} else if (user_param_count > param_count) {
ACPI_WARNING((AE_INFO,
"%s: Excess arguments - needs %d, found %d",
pathname, param_count, user_param_count));
}
return;
}

/* Allow two different legal argument counts (_SCP, etc.) */

required_params_current = predefined->info.param_count & 0x0F;
required_params_old = predefined->info.param_count >> 4;

if (user_param_count != ACPI_UINT32_MAX) {

/* Validate the user-supplied parameter count */

if ((user_param_count != required_params_current) &&
(user_param_count != required_params_old)) {
ACPI_WARNING((AE_INFO,
"%s: Parameter count mismatch - caller passed %d, ACPI requires %d",
pathname, user_param_count,
required_params_current));
}
}

/*
* Only validate the argument count on the first successful evaluation of
* the method. This ensures that any warnings will only be emitted during
* the very first evaluation of the method/object.
*/
if (node->flags & ANOBJ_EVALUATED) {
return;
}

/*
* Check that the ASL-defined parameter count is what is expected for
* this predefined name.
*/
if ((param_count != required_params_current) &&
(param_count != required_params_old)) {
ACPI_WARNING((AE_INFO,
"%s: Parameter count mismatch - ASL declared %d, expected %d",
"%s: Parameter count mismatch - ASL declared %d, ACPI requires %d",
pathname, param_count, required_params_current));
}
}
Expand Down
3 changes: 3 additions & 0 deletions include/acpi/acnamesp.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
*/
acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
u32 user_param_count,
acpi_status return_status,
union acpi_operand_object **return_object);

const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
Expand All @@ -191,6 +193,7 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
void
acpi_ns_check_parameter_count(char *pathname,
struct acpi_namespace_node *node,
u32 user_param_count,
const union acpi_predefined_info *info);

/*
Expand Down

0 comments on commit eeb4437

Please sign in to comment.