[ACPI] ACPICA 20051216
Implemented optional support to allow unresolved names within ASL Package objects. A null object is inserted in the package when a named reference cannot be located in the current namespace. Enabled via the interpreter slack flag which Linux has enabled by default (acpi=strict to disable slack). This should eliminate AE_NOT_FOUND exceptions seen on machines that contain such code. Implemented an optimization to the initialization sequence that can improve boot time. During ACPI device initialization, the _STA method is now run if and only if the _INI method exists. The _STA method is used to determine if the device is present; An _INI can only be run if _STA returns present, but it is a waste of time to run the _STA method if the _INI does not exist. (Prototype and assistance from Dong Wei) Implemented use of the C99 uintptr_t for the pointer casting macros if it is available in the current compiler. Otherwise, the default (void *) cast is used as before. Fixed some possible memory leaks found within the execution path of the Break, Continue, If, and CreateField operators. (Valery Podrezov) Fixed a problem introduced in the 20051202 release where an exception is generated during method execution if a control method attempts to declare another method. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
@ -47,10 +47,68 @@
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acdisasm.h>
|
||||
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsmethod")
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_method_error
|
||||
*
|
||||
* PARAMETERS: Status - Execution status
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Called on method error. Invoke the global exception handler if
|
||||
* present, dump the method data if the disassembler is configured
|
||||
*
|
||||
* Note: Allows the exception handler to change the status code
|
||||
*
|
||||
******************************************************************************/
|
||||
acpi_status
|
||||
acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
|
||||
{
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
/* Ignore AE_OK and control exception codes */
|
||||
|
||||
if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Invoke the global exception handler */
|
||||
|
||||
if (acpi_gbl_exception_handler) {
|
||||
/* Exit the interpreter, allow handler to execute methods */
|
||||
|
||||
acpi_ex_exit_interpreter();
|
||||
|
||||
/*
|
||||
* Handler can map the exception code to anything it wants, including
|
||||
* AE_OK, in which case the executing method will not be aborted.
|
||||
*/
|
||||
status = acpi_gbl_exception_handler(status,
|
||||
walk_state->method_node ?
|
||||
walk_state->method_node->
|
||||
name.integer : 0,
|
||||
walk_state->opcode,
|
||||
walk_state->aml_offset,
|
||||
NULL);
|
||||
(void)acpi_ex_enter_interpreter();
|
||||
}
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
if (ACPI_FAILURE(status)) {
|
||||
/* Display method locals/args if disassembler is present */
|
||||
|
||||
acpi_dm_dump_method_info(status, walk_state, walk_state->op);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_begin_method_execution
|
||||
@ -66,10 +124,11 @@ ACPI_MODULE_NAME("dsmethod")
|
||||
* for clearance to execute.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_namespace_node *calling_method_node)
|
||||
acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
|
||||
union acpi_operand_object * obj_desc,
|
||||
struct acpi_namespace_node * calling_method_node)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsobject")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
@ -85,7 +86,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
*obj_desc_ptr = NULL;
|
||||
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
|
||||
/*
|
||||
* This is an named object reference. If this name was
|
||||
* This is a named object reference. If this name was
|
||||
* previously looked up in the namespace, it was stored in this op.
|
||||
* Otherwise, go ahead and look it up now
|
||||
*/
|
||||
@ -96,18 +97,48 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT |
|
||||
ACPI_NS_DONT_OPEN_SCOPE, NULL,
|
||||
(struct acpi_namespace_node **)
|
||||
&(op->common.node));
|
||||
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_namespace_node,
|
||||
&(op->
|
||||
common.
|
||||
node)));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_REPORT_NSERROR(op->common.value.string,
|
||||
status);
|
||||
/* Check if we are resolving a named reference within a package */
|
||||
|
||||
if ((status == AE_NOT_FOUND)
|
||||
&& (acpi_gbl_enable_interpreter_slack)
|
||||
&&
|
||||
((op->common.parent->common.aml_opcode ==
|
||||
AML_PACKAGE_OP)
|
||||
|| (op->common.parent->common.aml_opcode ==
|
||||
AML_VAR_PACKAGE_OP))) {
|
||||
/*
|
||||
* We didn't find the target and we are populating elements
|
||||
* of a package - ignore if slack enabled. Some ASL code
|
||||
* contains dangling invalid references in packages and
|
||||
* expects that no exception will be issued. Leave the
|
||||
* element as a null element. It cannot be used, but it
|
||||
* can be overwritten by subsequent ASL code - this is
|
||||
* typically the case.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Ignoring unresolved reference in package [%4.4s]\n",
|
||||
walk_state->
|
||||
scope_info->scope.
|
||||
node->name.ascii));
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
} else {
|
||||
ACPI_REPORT_NSERROR(op->common.value.
|
||||
string, status);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create and init the internal ACPI object */
|
||||
/* Create and init a new internal ACPI object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
|
||||
(op->common.aml_opcode))->
|
||||
@ -157,13 +188,13 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
|
||||
|
||||
ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
|
||||
|
||||
/*
|
||||
* If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
|
||||
* The buffer object already exists (from the NS node), otherwise it must
|
||||
* be created.
|
||||
*/
|
||||
obj_desc = *obj_desc_ptr;
|
||||
if (obj_desc) {
|
||||
/*
|
||||
* We are evaluating a Named buffer object "Name (xxxx, Buffer)".
|
||||
* The buffer object already exists (from the NS node)
|
||||
*/
|
||||
} else {
|
||||
if (!obj_desc) {
|
||||
/* Create a new buffer object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
|
||||
@ -259,7 +290,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
u32 package_list_length;
|
||||
acpi_status status = AE_OK;
|
||||
u32 i;
|
||||
acpi_native_uint i;
|
||||
|
||||
ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
|
||||
|
||||
@ -271,13 +302,12 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
parent = parent->common.parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are evaluating a Named package object "Name (xxxx, Package)",
|
||||
* the package object already exists, otherwise it must be created.
|
||||
*/
|
||||
obj_desc = *obj_desc_ptr;
|
||||
if (obj_desc) {
|
||||
/*
|
||||
* We are evaluating a Named package object "Name (xxxx, Package)".
|
||||
* Get the existing package object from the NS node
|
||||
*/
|
||||
} else {
|
||||
if (!obj_desc) {
|
||||
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
|
||||
*obj_desc_ptr = obj_desc;
|
||||
if (!obj_desc) {
|
||||
@ -291,11 +321,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Count the number of items in the package list */
|
||||
|
||||
package_list_length = 0;
|
||||
arg = op->common.value.arg;
|
||||
arg = arg->common.next;
|
||||
while (arg) {
|
||||
package_list_length++;
|
||||
for (package_list_length = 0; arg; package_list_length++) {
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
@ -322,12 +350,11 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
}
|
||||
|
||||
/*
|
||||
* Now init the elements of the package
|
||||
* Initialize all elements of the package
|
||||
*/
|
||||
i = 0;
|
||||
arg = op->common.value.arg;
|
||||
arg = arg->common.next;
|
||||
while (arg) {
|
||||
for (i = 0; arg; i++) {
|
||||
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
|
||||
/* Object (package or buffer) is already built */
|
||||
|
||||
@ -340,8 +367,6 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
package.
|
||||
elements[i]);
|
||||
}
|
||||
|
||||
i++;
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
|
@ -314,12 +314,13 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
case AML_CLASS_EXECUTE:
|
||||
case AML_CLASS_CREATE:
|
||||
|
||||
/*
|
||||
* Most operators with arguments.
|
||||
* Start a new result/operand state
|
||||
*/
|
||||
status = acpi_ds_result_stack_push(walk_state);
|
||||
if (walk_state->opcode != AML_CREATE_FIELD_OP) {
|
||||
status = acpi_ds_result_stack_push(walk_state);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -723,20 +724,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Invoke exception handler on error */
|
||||
|
||||
if (ACPI_FAILURE(status) &&
|
||||
acpi_gbl_exception_handler && !(status & AE_CODE_CONTROL)) {
|
||||
acpi_ex_exit_interpreter();
|
||||
status = acpi_gbl_exception_handler(status,
|
||||
walk_state->method_node->
|
||||
name.integer,
|
||||
walk_state->opcode,
|
||||
walk_state->aml_offset,
|
||||
NULL);
|
||||
(void)acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
if (walk_state->result_obj) {
|
||||
/* Break to debugger to display result */
|
||||
|
||||
@ -758,18 +745,14 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Invoke exception handler on error */
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = acpi_ds_method_error(status, walk_state);
|
||||
}
|
||||
|
||||
/* Always clear the object stack */
|
||||
|
||||
walk_state->num_operands = 0;
|
||||
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
|
||||
/* On error, display method locals/args */
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_dm_dump_method_info(status, walk_state, op);
|
||||
}
|
||||
#endif
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
@ -428,43 +428,54 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
|
||||
}
|
||||
}
|
||||
|
||||
if (op->common.aml_opcode == AML_METHOD_OP) {
|
||||
/*
|
||||
* method_op pkg_length name_string method_flags term_list
|
||||
*
|
||||
* Note: We must create the method node/object pair as soon as we
|
||||
* see the method declaration. This allows later pass1 parsing
|
||||
* of invocations of the method (need to know the number of
|
||||
* arguments.)
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"LOADING-Method: State=%p Op=%p named_obj=%p\n",
|
||||
walk_state, op, op->named.node));
|
||||
/*
|
||||
* If we are executing a method, do not create any namespace objects
|
||||
* during the load phase, only during execution.
|
||||
*/
|
||||
if (!walk_state->method_node) {
|
||||
if (op->common.aml_opcode == AML_METHOD_OP) {
|
||||
/*
|
||||
* method_op pkg_length name_string method_flags term_list
|
||||
*
|
||||
* Note: We must create the method node/object pair as soon as we
|
||||
* see the method declaration. This allows later pass1 parsing
|
||||
* of invocations of the method (need to know the number of
|
||||
* arguments.)
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"LOADING-Method: State=%p Op=%p named_obj=%p\n",
|
||||
walk_state, op, op->named.node));
|
||||
|
||||
if (!acpi_ns_get_attached_object(op->named.node)) {
|
||||
walk_state->operands[0] = (void *)op->named.node;
|
||||
walk_state->num_operands = 1;
|
||||
if (!acpi_ns_get_attached_object(op->named.node)) {
|
||||
walk_state->operands[0] =
|
||||
ACPI_CAST_PTR(void, op->named.node);
|
||||
walk_state->num_operands = 1;
|
||||
|
||||
status =
|
||||
acpi_ds_create_operands(walk_state,
|
||||
op->common.value.arg);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
status = acpi_ex_create_method(op->named.data,
|
||||
op->named.length,
|
||||
walk_state);
|
||||
}
|
||||
walk_state->operands[0] = NULL;
|
||||
walk_state->num_operands = 0;
|
||||
status =
|
||||
acpi_ds_create_operands(walk_state,
|
||||
op->common.value.
|
||||
arg);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
status =
|
||||
acpi_ex_create_method(op->named.
|
||||
data,
|
||||
op->named.
|
||||
length,
|
||||
walk_state);
|
||||
}
|
||||
walk_state->operands[0] = NULL;
|
||||
walk_state->num_operands = 0;
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop the scope stack */
|
||||
/* Pop the scope stack (only if loading a table) */
|
||||
|
||||
if (acpi_ns_opens_scope(object_type)) {
|
||||
if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"(%s): Popping scope for Op %p\n",
|
||||
acpi_ut_get_type_name(object_type), op));
|
||||
@ -1015,11 +1026,50 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
|
||||
|
||||
status = acpi_ds_create_node(walk_state, node, op);
|
||||
break;
|
||||
|
||||
case AML_METHOD_OP:
|
||||
/*
|
||||
* method_op pkg_length name_string method_flags term_list
|
||||
*
|
||||
* Note: We must create the method node/object pair as soon as we
|
||||
* see the method declaration. This allows later pass1 parsing
|
||||
* of invocations of the method (need to know the number of
|
||||
* arguments.)
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"LOADING-Method: State=%p Op=%p named_obj=%p\n",
|
||||
walk_state, op, op->named.node));
|
||||
|
||||
if (!acpi_ns_get_attached_object(op->named.node)) {
|
||||
walk_state->operands[0] =
|
||||
ACPI_CAST_PTR(void, op->named.node);
|
||||
walk_state->num_operands = 1;
|
||||
|
||||
status =
|
||||
acpi_ds_create_operands(walk_state,
|
||||
op->common.value.
|
||||
arg);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
status =
|
||||
acpi_ex_create_method(op->named.
|
||||
data,
|
||||
op->named.
|
||||
length,
|
||||
walk_state);
|
||||
}
|
||||
walk_state->operands[0] = NULL;
|
||||
walk_state->num_operands = 0;
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* ACPI_NO_METHOD_EXECUTION */
|
||||
|
||||
default:
|
||||
/* All NAMED_COMPLEX opcodes must be handled above */
|
||||
/* Note: Method objects were already created in Pass 1 */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
Reference in New Issue
Block a user