mirror of
https://github.com/acpica/acpica/
synced 2025-01-15 05:49:18 +03:00
Add a mechanism to escape infinite AML While() loops.
Add a loop counter to force exit from AML While loops if the count becomes too large. 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. The maximum loop count is configurable. A new exception code is returned when a loop is broken, AE_AML_INFINITE_LOOP. Bob Moore, Alexey Starikovskiy.
This commit is contained in:
parent
d2a82ede58
commit
dc3e72f35a
@ -1430,12 +1430,30 @@ AcpiDsExecEndControlOp (
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
|
||||
|
||||
if (WalkState->ControlState->Common.Value)
|
||||
ControlState = WalkState->ControlState;
|
||||
if (ControlState->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.
|
||||
*/
|
||||
ControlState->Control.LoopCount++;
|
||||
if (ControlState->Control.LoopCount > 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;
|
||||
WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart;
|
||||
WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -193,6 +193,10 @@
|
||||
|
||||
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
|
||||
|
||||
/* Maximum number of While() loop iterations before forced abort */
|
||||
|
||||
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@ -231,8 +231,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
|
||||
|
||||
|
||||
/*
|
||||
@ -352,6 +353,7 @@ char const *AcpiGbl_ExceptionNames_Aml[] =
|
||||
"AE_AML_CIRCULAR_REFERENCE",
|
||||
"AE_AML_BAD_RESOURCE_LENGTH",
|
||||
"AE_AML_ILLEGAL_ADDRESS",
|
||||
"AE_AML_INFINITE_LOOP"
|
||||
};
|
||||
|
||||
char const *AcpiGbl_ExceptionNames_Ctrl[] =
|
||||
|
@ -731,6 +731,7 @@ typedef struct acpi_control_state
|
||||
union acpi_parse_object *PredicateOp;
|
||||
UINT8 *AmlPredicateStart; /* Start of if/while predicate */
|
||||
UINT8 *PackageEnd; /* End of if/while block */
|
||||
UINT32 LoopCount; /* While() loop counter */
|
||||
|
||||
} ACPI_CONTROL_STATE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user