Commit eeb4437e authored by Bob Moore's avatar Bob Moore Committed by Len Brown

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: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a647b5c3
......@@ -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:
......@@ -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);
......@@ -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 */
......
......@@ -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;
......@@ -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 */
......@@ -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
......@@ -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) {
......@@ -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);
}
......@@ -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
......@@ -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));
}
}
......
......@@ -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
......@@ -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);
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment