forked from Minki/linux
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>
This commit is contained in:
parent
a647b5c340
commit
eeb4437e63
@ -89,6 +89,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
|
|||||||
/* Initialize the return value to an invalid object */
|
/* Initialize the return value to an invalid object */
|
||||||
|
|
||||||
info->return_object = NULL;
|
info->return_object = NULL;
|
||||||
|
info->param_count = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the actual namespace node for the target object. Handles these cases:
|
* 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);
|
return_ACPI_STATUS(AE_NULL_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Count the number of arguments being passed to the method */
|
||||||
* Calculate the number of arguments being passed to the method
|
|
||||||
*/
|
|
||||||
|
|
||||||
info->param_count = 0;
|
|
||||||
if (info->parameters) {
|
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++;
|
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_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
|
||||||
ACPI_LV_INFO, _COMPONENT);
|
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 */
|
/*
|
||||||
|
* Check input argument count against the ASL-defined count for a method.
|
||||||
if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
|
* Also check predefined names: argument count and return value against
|
||||||
/*
|
* the ACPI specification. Some incorrect return value types are repaired.
|
||||||
* If this is the first evaluation, check the return value. This
|
*/
|
||||||
* ensures that any warnings will only be emitted during the very
|
(void)acpi_ns_check_predefined_names(node, info->param_count,
|
||||||
* first evaluation of the object.
|
status, &info->return_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 if there is a return value that must be dealt with */
|
/* 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_status
|
||||||
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
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_ptr)
|
||||||
{
|
{
|
||||||
union acpi_operand_object *return_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 */
|
/* Match the name for this method/object against the predefined list */
|
||||||
|
|
||||||
predefined = acpi_ns_check_for_predefined_name(node);
|
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 */
|
/* 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
|
* Check that the parameter count for this method matches the ASL
|
||||||
* with the ACPI specification.
|
* 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
|
* 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
|
* We have a return value, but if one wasn't expected, just exit, this is
|
||||||
* not a problem
|
* 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
|
* always return a value
|
||||||
*/
|
*/
|
||||||
if (!predefined->info.expected_btypes) {
|
if (!predefined->info.expected_btypes) {
|
||||||
@ -204,7 +227,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (pathname) {
|
if (pathname != predefined->info.name) {
|
||||||
ACPI_FREE(pathname);
|
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)
|
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
|
||||||
* Node - Namespace node for the method/object
|
* 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
|
* Predefined - Pointer to entry in predefined name table
|
||||||
*
|
*
|
||||||
* RETURN: None
|
* RETURN: None
|
||||||
@ -230,32 +254,76 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
|||||||
void
|
void
|
||||||
acpi_ns_check_parameter_count(char *pathname,
|
acpi_ns_check_parameter_count(char *pathname,
|
||||||
struct acpi_namespace_node *node,
|
struct acpi_namespace_node *node,
|
||||||
|
u32 user_param_count,
|
||||||
const union acpi_predefined_info *predefined)
|
const union acpi_predefined_info *predefined)
|
||||||
{
|
{
|
||||||
u32 param_count;
|
u32 param_count;
|
||||||
u32 required_params_current;
|
u32 required_params_current;
|
||||||
u32 required_params_old;
|
u32 required_params_old;
|
||||||
|
|
||||||
/*
|
/* Methods have 0-7 parameters. All other types have zero. */
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
param_count = 0;
|
param_count = 0;
|
||||||
if (node->type == ACPI_TYPE_METHOD) {
|
if (node->type == ACPI_TYPE_METHOD) {
|
||||||
param_count = node->object->method.param_count;
|
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_current = predefined->info.param_count & 0x0F;
|
||||||
required_params_old = predefined->info.param_count >> 4;
|
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) &&
|
if ((param_count != required_params_current) &&
|
||||||
(param_count != required_params_old)) {
|
(param_count != required_params_old)) {
|
||||||
ACPI_WARNING((AE_INFO,
|
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));
|
pathname, param_count, required_params_current));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
|
|||||||
*/
|
*/
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
|
||||||
|
u32 user_param_count,
|
||||||
|
acpi_status return_status,
|
||||||
union acpi_operand_object **return_object);
|
union acpi_operand_object **return_object);
|
||||||
|
|
||||||
const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
|
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
|
void
|
||||||
acpi_ns_check_parameter_count(char *pathname,
|
acpi_ns_check_parameter_count(char *pathname,
|
||||||
struct acpi_namespace_node *node,
|
struct acpi_namespace_node *node,
|
||||||
|
u32 user_param_count,
|
||||||
const union acpi_predefined_info *info);
|
const union acpi_predefined_info *info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user