summaryrefslogtreecommitdiff
path: root/drivers/acpi/acpica/nseval.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2013-05-30 06:00:01 +0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-01 23:54:30 +0400
commit29a241cc02110b8b2259fd72719b8cadc03909be (patch)
treea96c10dd22a35479dc2e1ef140f7d90a442f9c03 /drivers/acpi/acpica/nseval.c
parente1405ca5ebf1068a0d62afd2fec8f0354038147a (diff)
downloadlinux-29a241cc02110b8b2259fd72719b8cadc03909be.tar.xz
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/nseval.c')
-rw-r--r--drivers/acpi/acpica/nseval.c247
1 files changed, 142 insertions, 105 deletions
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index b61db69d5675..18108bc2e51c 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -61,7 +61,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
*
* PARAMETERS: info - Evaluation info block, contains:
* prefix_node - Prefix or Method/Object Node to execute
- * pathname - Name of method to execute, If NULL, the
+ * relative_path - Name of method to execute, If NULL, the
* Node is the object to execute
* parameters - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
@@ -82,10 +82,9 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
*
******************************************************************************/
-acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
{
acpi_status status;
- struct acpi_namespace_node *node;
ACPI_FUNCTION_TRACE(ns_evaluate);
@@ -93,83 +92,138 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Initialize the return value to an invalid object */
-
- info->return_object = NULL;
- info->param_count = 0;
-
- if (!info->resolved_node) {
+ if (!info->node) {
/*
- * Get the actual namespace node for the target object if we need to.
- * Handles these cases:
+ * Get the actual namespace node for the target object if we
+ * need to. Handles these cases:
*
- * 1) Null node, Pathname (absolute path)
- * 2) Node, Pathname (path relative to Node)
- * 3) Node, Null Pathname
+ * 1) Null node, valid pathname from root (absolute path)
+ * 2) Node and valid pathname (path relative to Node)
+ * 3) Node, Null pathname
*/
- status = acpi_ns_get_node(info->prefix_node, info->pathname,
- ACPI_NS_NO_UPSEARCH,
- &info->resolved_node);
+ status =
+ acpi_ns_get_node(info->prefix_node, info->relative_pathname,
+ ACPI_NS_NO_UPSEARCH, &info->node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/*
- * For a method alias, we must grab the actual method node so that proper
- * scoping context will be established before execution.
+ * For a method alias, we must grab the actual method node so that
+ * proper scoping context will be established before execution.
*/
- if (acpi_ns_get_type(info->resolved_node) ==
- ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- info->resolved_node =
+ if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ info->node =
ACPI_CAST_PTR(struct acpi_namespace_node,
- info->resolved_node->object);
+ info->node->object);
+ }
+
+ /* Complete the info block initialization */
+
+ info->return_object = NULL;
+ info->node_flags = info->node->flags;
+ info->obj_desc = acpi_ns_get_attached_object(info->node);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
+ info->relative_pathname, info->node,
+ acpi_ns_get_attached_object(info->node)));
+
+ /* Get info if we have a predefined name (_HID, etc.) */
+
+ info->predefined =
+ acpi_ut_match_predefined_method(info->node->name.ascii);
+
+ /* Get the full pathname to the object, for use in warning messages */
+
+ info->full_pathname = acpi_ns_get_external_pathname(info->node);
+ if (!info->full_pathname) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname,
- info->resolved_node,
- acpi_ns_get_attached_object(info->resolved_node)));
+ /* Count the number of arguments being passed in */
+
+ info->param_count = 0;
+ if (info->parameters) {
+ while (info->parameters[info->param_count]) {
+ info->param_count++;
+ }
+
+ /* Warn on impossible argument count */
+
+ if (info->param_count > ACPI_METHOD_NUM_ARGS) {
+ ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+ ACPI_WARN_ALWAYS,
+ "Excess arguments (%u) - using only %u",
+ info->param_count,
+ ACPI_METHOD_NUM_ARGS));
+
+ info->param_count = ACPI_METHOD_NUM_ARGS;
+ }
+ }
+
+ /*
+ * For predefined names: Check that the declared argument count
+ * matches the ACPI spec -- otherwise this is a BIOS error.
+ */
+ acpi_ns_check_acpi_compliance(info->full_pathname, info->node,
+ info->predefined);
+
+ /*
+ * For all names: Check that the incoming argument count for
+ * this method/object matches the actual ASL/AML definition.
+ */
+ acpi_ns_check_argument_count(info->full_pathname, info->node,
+ info->param_count, info->predefined);
- node = info->resolved_node;
+ /* For predefined names: Typecheck all incoming arguments */
+
+ acpi_ns_check_argument_types(info);
/*
- * Two major cases here:
+ * Three major evaluation cases:
*
- * 1) The object is a control method -- execute it
- * 2) The object is not a method -- just return it's current value
+ * 1) Object types that cannot be evaluated by definition
+ * 2) The object is a control method -- execute it
+ * 3) The object is not a method -- just return it's current value
*/
- if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) {
+ switch (acpi_ns_get_type(info->node)) {
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_EVENT:
+ case ACPI_TYPE_MUTEX:
+ case ACPI_TYPE_REGION:
+ case ACPI_TYPE_THERMAL:
+ case ACPI_TYPE_LOCAL_SCOPE:
+ /*
+ * 1) Disallow evaluation of certain object types. For these,
+ * object evaluation is undefined and not supported.
+ */
+ ACPI_ERROR((AE_INFO,
+ "%s: Evaluation of object type [%s] is not supported",
+ info->full_pathname,
+ acpi_ut_get_type_name(info->node->type)));
+
+ status = AE_TYPE;
+ goto cleanup;
+
+ case ACPI_TYPE_METHOD:
/*
- * 1) Object is a control method - execute it
+ * 2) Object is a control method - execute it
*/
/* Verify that there is a method object associated with this node */
- info->obj_desc =
- acpi_ns_get_attached_object(info->resolved_node);
if (!info->obj_desc) {
ACPI_ERROR((AE_INFO,
- "Control method has no attached sub-object"));
- return_ACPI_STATUS(AE_NULL_OBJECT);
+ "%s: Method has no attached sub-object",
+ info->full_pathname));
+ status = AE_NULL_OBJECT;
+ goto cleanup;
}
- /* Count the number of arguments being passed to the method */
-
- if (info->parameters) {
- while (info->parameters[info->param_count]) {
- if (info->param_count > ACPI_METHOD_MAX_ARG) {
- return_ACPI_STATUS(AE_LIMIT);
- }
- info->param_count++;
- }
- }
-
-
- ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method",
- ACPI_LV_INFO, _COMPONENT);
-
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Method at AML address %p Length %X\n",
+ "**** Execute method [%s] at AML address %p length %X\n",
+ info->full_pathname,
info->obj_desc->method.aml_start + 1,
info->obj_desc->method.aml_length - 1));
@@ -184,81 +238,61 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
acpi_ex_enter_interpreter();
status = acpi_ps_execute_method(info);
acpi_ex_exit_interpreter();
- } else {
+ break;
+
+ default:
/*
- * 2) Object is not a method, return its current value
- *
- * Disallow certain object types. For these, "evaluation" is undefined.
+ * 3) All other non-method objects -- get the current object value
*/
- switch (info->resolved_node->type) {
- case ACPI_TYPE_DEVICE:
- case ACPI_TYPE_EVENT:
- case ACPI_TYPE_MUTEX:
- case ACPI_TYPE_REGION:
- case ACPI_TYPE_THERMAL:
- case ACPI_TYPE_LOCAL_SCOPE:
-
- ACPI_ERROR((AE_INFO,
- "[%4.4s] Evaluation of object type [%s] is not supported",
- info->resolved_node->name.ascii,
- acpi_ut_get_type_name(info->resolved_node->
- type)));
-
- return_ACPI_STATUS(AE_TYPE);
-
- default:
- break;
- }
/*
- * Objects require additional resolution steps (e.g., the Node may be
- * a field that must be read, etc.) -- we can't just grab the object
- * out of the node.
+ * Some objects require additional resolution steps (e.g., the Node
+ * may be a field that must be read, etc.) -- we can't just grab
+ * the object out of the node.
*
* Use resolve_node_to_value() to get the associated value.
*
* NOTE: we can get away with passing in NULL for a walk state because
- * resolved_node is guaranteed to not be a reference to either a method
+ * the Node is guaranteed to not be a reference to either a method
* local or a method argument (because this interface is never called
* from a running method.)
*
* Even though we do not directly invoke the interpreter for object
- * resolution, we must lock it because we could access an opregion.
- * The opregion access code assumes that the interpreter is locked.
+ * resolution, we must lock it because we could access an op_region.
+ * The op_region access code assumes that the interpreter is locked.
*/
acpi_ex_enter_interpreter();
- /* Function has a strange interface */
+ /* TBD: resolve_node_to_value has a strange interface, fix */
+
+ info->return_object =
+ ACPI_CAST_PTR(union acpi_operand_object, info->node);
status =
- acpi_ex_resolve_node_to_value(&info->resolved_node, NULL);
+ acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
+ (struct acpi_namespace_node,
+ &info->return_object), NULL);
acpi_ex_exit_interpreter();
- /*
- * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
- * in resolved_node.
- */
- if (ACPI_SUCCESS(status)) {
- status = AE_CTRL_RETURN_VALUE;
- info->return_object =
- ACPI_CAST_PTR(union acpi_operand_object,
- info->resolved_node);
-
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "Returning object %p [%s]\n",
- info->return_object,
- acpi_ut_get_object_type_name(info->
- return_object)));
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n",
+ info->return_object,
+ acpi_ut_get_object_type_name(info->
+ return_object)));
+
+ status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */
+ break;
}
/*
- * 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.
+ * For predefined names, check the 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);
+ (void)acpi_ns_check_return_value(info->node, info, info->param_count,
+ status, &info->return_object);
/* Check if there is a return value that must be dealt with */
@@ -278,12 +312,15 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"*** Completed evaluation of object %s ***\n",
- info->pathname));
+ info->relative_pathname));
+ cleanup:
/*
* Namespace was unlocked by the handling acpi_ns* function, so we
- * just return
+ * just free the pathname and return
*/
+ ACPI_FREE(info->full_pathname);
+ info->full_pathname = NULL;
return_ACPI_STATUS(status);
}