From 17ff34b08e0742f392ec2e3309df68ecc0fa49c0 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 12 Nov 2008 15:15:29 +0800 Subject: [PATCH] --- yaml --- r: 128023 b: refs/heads/master c: fc37445733aeae4fd1a20385850620354263b1d5 h: refs/heads/master i: 128021: 309665cc8b97ab2b484d13bd27fcc3f96fd50673 128019: 401d093b3d9670e7eb5b0f7da35d888ac16d2232 128015: ebc3fff90106d951fa3293df403884090a68e167 v: v3 --- [refs] | 2 +- trunk/drivers/acpi/dispatcher/dsopcode.c | 24 +++++++++++++++++++++--- trunk/include/acpi/acconfig.h | 4 ++++ trunk/include/acpi/acexcep.h | 4 +++- trunk/include/acpi/aclocal.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index f42eeaadbee9..d43398e35a43 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 96411a630412f057d365aa1e9de7d23c069d627a +refs/heads/master: fc37445733aeae4fd1a20385850620354263b1d5 diff --git a/trunk/drivers/acpi/dispatcher/dsopcode.c b/trunk/drivers/acpi/dispatcher/dsopcode.c index 5cd406676c2c..50c892a49fa3 100644 --- a/trunk/drivers/acpi/dispatcher/dsopcode.c +++ b/trunk/drivers/acpi/dispatcher/dsopcode.c @@ -1262,13 +1262,31 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); - if (walk_state->control_state->common.value) { + control_state = walk_state->control_state; + if (control_state->common.value) { - /* Predicate was true, go back and evaluate it again! */ + /* Predicate was true, the body of the loop was just executed */ + /* + * This loop counter mechanism allows the interpreter to escape + * possibly infinite loops. This can occur in poorly written AML + * when the hardware does not respond within a while loop and the + * loop does not implement a timeout. + */ + control_state->control.loop_count++; + if (control_state->control.loop_count > + ACPI_MAX_LOOP_ITERATIONS) { + status = AE_AML_INFINITE_LOOP; + break; + } + + /* + * Go back and evaluate the predicate and maybe execute the loop + * another time + */ status = AE_CTRL_PENDING; walk_state->aml_last_while = - walk_state->control_state->control.aml_predicate_start; + control_state->control.aml_predicate_start; break; } diff --git a/trunk/include/acpi/acconfig.h b/trunk/include/acpi/acconfig.h index 29feee27f0ea..e50fe7157463 100644 --- a/trunk/include/acpi/acconfig.h +++ b/trunk/include/acpi/acconfig.h @@ -119,6 +119,10 @@ #define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 +/* Maximum number of While() loop iterations before forced abort */ + +#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF + /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) diff --git a/trunk/include/acpi/acexcep.h b/trunk/include/acpi/acexcep.h index 84f5cb242863..a1ae1057d2ef 100644 --- a/trunk/include/acpi/acexcep.h +++ b/trunk/include/acpi/acexcep.h @@ -153,8 +153,9 @@ #define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x001E | AE_CODE_AML) #define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x001F | AE_CODE_AML) #define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0020 | AE_CODE_AML) +#define AE_AML_INFINITE_LOOP (acpi_status) (0x0021 | AE_CODE_AML) -#define AE_CODE_AML_MAX 0x0020 +#define AE_CODE_AML_MAX 0x0021 /* * Internal exceptions used for control @@ -267,6 +268,7 @@ char const *acpi_gbl_exception_names_aml[] = { "AE_AML_CIRCULAR_REFERENCE", "AE_AML_BAD_RESOURCE_LENGTH", "AE_AML_ILLEGAL_ADDRESS", + "AE_AML_INFINITE_LOOP" }; char const *acpi_gbl_exception_names_ctrl[] = { diff --git a/trunk/include/acpi/aclocal.h b/trunk/include/acpi/aclocal.h index ecab527cf78e..0323fa9aa3e6 100644 --- a/trunk/include/acpi/aclocal.h +++ b/trunk/include/acpi/aclocal.h @@ -566,6 +566,7 @@ struct acpi_control_state { union acpi_parse_object *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ + u32 loop_count; /* While() loop counter */ }; /*