Skip to content

Commit

Permalink
ACPICA 20050526 from Bob Moore <[email protected]>
Browse files Browse the repository at this point in the history
Implemented support to execute Type 1 and Type 2 AML
opcodes appearing at the module level (not within a control
method.)  These opcodes are executed exactly once at the
time the table is loaded. This type of code was legal up
until the release of ACPI 2.0B (2002) and is now supported
within ACPI CA in order to provide backwards compatibility
with earlier BIOS implementations. This eliminates the
"Encountered executable code at module level" warning that
was previously generated upon detection of such code.

Fixed a problem in the interpreter where an AE_NOT_FOUND
exception could inadvertently be generated during the
lookup of namespace objects in the second pass parse of
ACPI tables and control methods. It appears that this
problem could occur during the resolution of forward
references to namespace objects.

Added the ACPI_MUTEX_DEBUG #ifdef to the
acpi_ut_release_mutex function, corresponding to the same
the deadlock detection debug code to be compiled out in
the normal case, improving mutex performance (and overall
subsystem performance) considerably.  As suggested by
Alexey Starikovskiy.

Implemented a handful of miscellaneous fixes for possible
memory leaks on error conditions and error handling
control paths. These fixes were suggested by FreeBSD and
the Coverity Prevent source code analysis tool.

Added a check for a null RSDT pointer in
acpi_get_firmware_table (tbxfroot.c) to prevent a fault
in this error case.

Signed-off-by Len Brown <[email protected]>
  • Loading branch information
acpibob authored and lenb committed Jul 13, 2005
1 parent 6f42ccf commit 88ac00f
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 91 deletions.
8 changes: 5 additions & 3 deletions drivers/acpi/dispatcher/dsmethod.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,16 @@ acpi_ds_parse_method (

walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
if (!walk_state) {
return_ACPI_STATUS (AE_NO_MEMORY);
status = AE_NO_MEMORY;
goto cleanup;
}

status = acpi_ds_init_aml_walk (walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 1);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
goto cleanup;
}

/*
Expand All @@ -161,13 +162,14 @@ acpi_ds_parse_method (
*/
status = acpi_ps_parse_aml (walk_state);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
goto cleanup;
}

ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
"**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
acpi_ut_get_node_name (obj_handle), obj_handle, op));

cleanup:
acpi_ps_delete_parse_tree (op);
return_ACPI_STATUS (status);
}
Expand Down
15 changes: 9 additions & 6 deletions drivers/acpi/dispatcher/dsopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,15 @@ acpi_ds_execute_arguments (

walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
if (!walk_state) {
return_ACPI_STATUS (AE_NO_MEMORY);
status = AE_NO_MEMORY;
goto cleanup;
}

status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
aml_length, NULL, 1);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
goto cleanup;
}

/* Mark this parse as a deferred opcode */
Expand All @@ -138,8 +139,7 @@ acpi_ds_execute_arguments (

status = acpi_ps_parse_aml (walk_state);
if (ACPI_FAILURE (status)) {
acpi_ps_delete_parse_tree (op);
return_ACPI_STATUS (status);
goto cleanup;
}

/* Get and init the Op created above */
Expand All @@ -160,7 +160,8 @@ acpi_ds_execute_arguments (

walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
if (!walk_state) {
return_ACPI_STATUS (AE_NO_MEMORY);
status = AE_NO_MEMORY;
goto cleanup;
}

/* Execute the opcode and arguments */
Expand All @@ -169,13 +170,15 @@ acpi_ds_execute_arguments (
aml_length, NULL, 3);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
goto cleanup;
}

/* Mark this execution as a deferred opcode */

walk_state->deferred_node = node;
status = acpi_ps_parse_aml (walk_state);

cleanup:
acpi_ps_delete_parse_tree (op);
return_ACPI_STATUS (status);
}
Expand Down
56 changes: 37 additions & 19 deletions drivers/acpi/dispatcher/dswload.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,6 @@ acpi_ds_load1_begin_op (

if (op) {
if (!(walk_state->op_info->flags & AML_NAMED)) {
#if 0
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n",
walk_state->op_info->name);
*out_op = op;
return (AE_CTRL_SKIP);
}
#endif
*out_op = op;
return (AE_OK);
}
Expand Down Expand Up @@ -486,16 +477,30 @@ acpi_ds_load2_begin_op (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));

if (op) {
if ((walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
/* We are executing a while loop outside of a method */

status = acpi_ds_exec_begin_op (walk_state, out_op);
return_ACPI_STATUS (status);
}

/* We only care about Namespace opcodes here */

if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
(walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
(!(walk_state->op_info->flags & AML_NAMED))) {
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_REPORT_WARNING ((
"Encountered executable code at module level, [%s]\n",
acpi_ps_get_opcode_name (walk_state->opcode)));
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"Begin/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name,
walk_state->op_info->flags));

/* Executing a type1 or type2 opcode outside of a method */

status = acpi_ds_exec_begin_op (walk_state, out_op);
return_ACPI_STATUS (status);
}
return_ACPI_STATUS (AE_OK);
}
Expand Down Expand Up @@ -657,8 +662,10 @@ acpi_ds_load2_begin_op (
break;
}

/* Add new entry into namespace */

status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH,
ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
walk_state, &(node));
break;
}
Expand All @@ -668,7 +675,6 @@ acpi_ds_load2_begin_op (
return_ACPI_STATUS (status);
}


if (!op) {
/* Create a new op */

Expand All @@ -682,9 +688,7 @@ acpi_ds_load2_begin_op (
if (node) {
op->named.name = node->name.integer;
}
if (out_op) {
*out_op = op;
}
*out_op = op;
}

/*
Expand Down Expand Up @@ -731,9 +735,24 @@ acpi_ds_load2_end_op (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
walk_state->op_info->name, op, walk_state));

/* Only interested in opcodes that have namespace objects */
/* Check if opcode had an associated namespace object */

if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
#ifndef ACPI_NO_METHOD_EXECUTION
/* No namespace object. Executable opcode? */

if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"End/EXEC: %s (fl %8.8X)\n", walk_state->op_info->name,
walk_state->op_info->flags));

/* Executing a type1 or type2 opcode outside of a method */

status = acpi_ds_exec_end_op (walk_state);
return_ACPI_STATUS (status);
}
#endif
return_ACPI_STATUS (AE_OK);
}

Expand All @@ -742,7 +761,6 @@ acpi_ds_load2_end_op (
"Ending scope Op=%p State=%p\n", op, walk_state));
}


object_type = walk_state->op_info->object_type;

/*
Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/dispatcher/dswstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ acpi_ds_init_aml_walk (
/* The next_op of the next_walk will be the beginning of the method */

walk_state->next_op = NULL;
walk_state->pass_number = (u8) pass_number;

if (info) {
if (info->parameter_type == ACPI_PARAM_GPE) {
Expand Down
27 changes: 16 additions & 11 deletions drivers/acpi/executer/exconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,22 @@ acpi_ex_load_op (
*/
status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
if (ACPI_FAILURE (status)) {
goto cleanup;
return_ACPI_STATUS (status);
}

table_ptr = ACPI_CAST_PTR (struct acpi_table_header,
buffer_desc->buffer.pointer);

/* Sanity check the table length */
/* All done with the buffer_desc, delete it */

buffer_desc->buffer.pointer = NULL;
acpi_ut_remove_reference (buffer_desc);

/* Sanity check the table length */

if (table_ptr->length < sizeof (struct acpi_table_header)) {
return_ACPI_STATUS (AE_BAD_HEADER);
status = AE_BAD_HEADER;
goto cleanup;
}
break;

Expand Down Expand Up @@ -413,25 +419,24 @@ acpi_ex_load_op (

status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
if (ACPI_FAILURE (status)) {
goto cleanup;
/* On error, table_ptr was deallocated above */

return_ACPI_STATUS (status);
}

/* Store the ddb_handle into the Target operand */

status = acpi_ex_store (ddb_handle, target, walk_state);
if (ACPI_FAILURE (status)) {
(void) acpi_ex_unload_table (ddb_handle);
}

return_ACPI_STATUS (status);
/* table_ptr was deallocated above */

return_ACPI_STATUS (status);
}

cleanup:

if (buffer_desc) {
acpi_ut_remove_reference (buffer_desc);
}
else {
if (ACPI_FAILURE (status)) {
ACPI_MEM_FREE (table_ptr);
}
return_ACPI_STATUS (status);
Expand Down
5 changes: 4 additions & 1 deletion drivers/acpi/executer/exfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ acpi_ex_read_data_from_field (
if (!obj_desc) {
return_ACPI_STATUS (AE_AML_NO_OPERAND);
}
if (!ret_buffer_desc) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}

if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
/*
Expand Down Expand Up @@ -182,7 +185,7 @@ acpi_ex_read_data_from_field (
if (ACPI_FAILURE (status)) {
acpi_ut_remove_reference (buffer_desc);
}
else if (ret_buffer_desc) {
else {
*ret_buffer_desc = buffer_desc;
}

Expand Down
7 changes: 7 additions & 0 deletions drivers/acpi/executer/exnames.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,13 @@ acpi_ex_get_name_string (
status = AE_AML_BAD_NAME;
}

if (ACPI_FAILURE (status)) {
if (name_string) {
ACPI_MEM_FREE (name_string);
}
return_ACPI_STATUS (status);
}

*out_name_string = name_string;
*out_name_length = (u32) (aml_address - in_aml_address);

Expand Down
11 changes: 6 additions & 5 deletions drivers/acpi/executer/exoparg1.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,16 @@ acpi_ex_opcode_0A_0T_1R (

cleanup:

if (!walk_state->result_obj) {
walk_state->result_obj = return_desc;
}

/* Delete return object on error */

if (ACPI_FAILURE (status)) {
if ((ACPI_FAILURE (status)) || walk_state->result_obj) {
acpi_ut_remove_reference (return_desc);
}
else {
/* Save the return value */

walk_state->result_obj = return_desc;
}

return_ACPI_STATUS (status);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/acpi/namespace/nsparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ acpi_ns_parse_table (
* to service the entire parse. The second pass of the parse then
* performs another complete parse of the AML..
*/
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 1\n"));
status = acpi_ns_one_complete_parse (1, table_desc);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
Expand All @@ -160,6 +161,7 @@ acpi_ns_parse_table (
* overhead of this is compensated for by the fact that the
* parse objects are all cached.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Start pass 2\n"));
status = acpi_ns_one_complete_parse (2, table_desc);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
Expand Down
Loading

0 comments on commit 88ac00f

Please sign in to comment.