diff options
Diffstat (limited to 'sys/contrib/dev/acpica/psloop.c')
-rw-r--r-- | sys/contrib/dev/acpica/psloop.c | 1389 |
1 files changed, 824 insertions, 565 deletions
diff --git a/sys/contrib/dev/acpica/psloop.c b/sys/contrib/dev/acpica/psloop.c index 91933c7..6c6ce47 100644 --- a/sys/contrib/dev/acpica/psloop.c +++ b/sys/contrib/dev/acpica/psloop.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psloop - Main AML parse loop - * $Revision: 1.5 $ + * $Revision: 1.16 $ * *****************************************************************************/ @@ -9,7 +9,7 @@ * * 1. Copyright Notice * - * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp. + * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. * All rights reserved. * * 2. License @@ -116,12 +116,11 @@ /* - * Parse the AML and build an operation tree as most interpreters, - * like Perl, do. Parsing is done by hand rather than with a YACC - * generated parser to tightly constrain stack and dynamic memory - * usage. At the same time, parsing is kept flexible and the code - * fairly compact by parsing based on a list of AML opcode - * templates in AmlOpInfo[] + * Parse the AML and build an operation tree as most interpreters, (such as + * Perl) do. Parsing is done by hand rather than with a YACC generated parser + * to tightly constrain stack and dynamic memory usage. Parsing is kept + * flexible and the code fairly compact by parsing based on a list of AML + * opcode templates in AmlOpInfo[]. */ #include <contrib/dev/acpica/acpi.h> @@ -135,727 +134,739 @@ static UINT32 AcpiGbl_Depth = 0; +/* Local prototypes */ + +static ACPI_STATUS +AcpiPsGetAmlOpcode ( + ACPI_WALK_STATE *WalkState); + +static ACPI_STATUS +AcpiPsBuildNamedOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *UnnamedOp, + ACPI_PARSE_OBJECT **Op); + +static ACPI_STATUS +AcpiPsCreateOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT **NewOp); + +static ACPI_STATUS +AcpiPsGetArguments ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *Op); + +static ACPI_STATUS +AcpiPsCompleteOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **Op, + ACPI_STATUS Status); + +static ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status); + + /******************************************************************************* * - * FUNCTION: AcpiPsParseLoop + * FUNCTION: AcpiPsGetAmlOpcode * * PARAMETERS: WalkState - Current state * * RETURN: Status * - * DESCRIPTION: Parse AML (pointed to by the current parser state) and return - * a tree of ops. + * DESCRIPTION: Extract the next AML opcode from the input stream. * ******************************************************************************/ -ACPI_STATUS -AcpiPsParseLoop ( +static ACPI_STATUS +AcpiPsGetAmlOpcode ( ACPI_WALK_STATE *WalkState) { - ACPI_STATUS Status = AE_OK; - ACPI_STATUS Status2; - ACPI_PARSE_OBJECT *Op = NULL; /* current op */ - ACPI_PARSE_OBJECT *Arg = NULL; - ACPI_PARSE_OBJECT *PreOp = NULL; - ACPI_PARSE_STATE *ParserState; - UINT8 *AmlOpStart = NULL; + ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); - ACPI_FUNCTION_TRACE_PTR ("PsParseLoop", WalkState); - if (WalkState->DescendingCallback == NULL) + WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, + WalkState->ParserState.AmlStart); + WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); + + switch (WalkState->OpInfo->Class) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + WalkState->Opcode = AML_INT_NAMEPATH_OP; + WalkState->ArgTypes = ARGP_NAMESTRING; + break; - ParserState = &WalkState->ParserState; - WalkState->ArgTypes = 0; + case AML_CLASS_UNKNOWN: -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + /* The opcode is unrecognized. Just skip unknown opcodes */ - if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) - { - /* We are restarting a preempted control method */ + ACPI_ERROR ((AE_INFO, + "Found unknown opcode %X at AML address %p offset %X, ignoring", + WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset)); - if (AcpiPsHasCompletedScope (ParserState)) - { - /* - * We must check if a predicate to an IF or WHILE statement - * was just completed - */ - if ((ParserState->Scope->ParseScope.Op) && - ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || - (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && - (WalkState->ControlState) && - (WalkState->ControlState->Common.State == - ACPI_CONTROL_PREDICATE_EXECUTING)) - { - /* - * A predicate was just completed, get the value of the - * predicate and branch based on that value - */ - WalkState->Op = NULL; - Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); - if (ACPI_FAILURE (Status) && - ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) - { - if (Status == AE_AML_NO_RETURN_VALUE) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Invoked method did not return a value, %s\n", - AcpiFormatException (Status))); + ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128); - } - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "GetPredicate Failed, %s\n", - AcpiFormatException (Status))); - return_ACPI_STATUS (Status); - } + /* Assume one-byte bad opcode */ - Status = AcpiPsNextParseState (WalkState, Op, Status); - } + WalkState->ParserState.Aml++; + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); - } - else if (WalkState->PrevOp) - { - /* We were in the middle of an op */ + default: - Op = WalkState->PrevOp; - WalkState->ArgTypes = WalkState->PrevArgTypes; - } + /* Found opcode info, this is a normal opcode */ + + WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); + WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; + break; } -#endif - /* Iterative parsing loop, while there is more AML to process: */ + return_ACPI_STATUS (AE_OK); +} - while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) - { - AmlOpStart = ParserState->Aml; - if (!Op) - { - /* Get the next opcode from the AML stream */ - WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (ParserState->Aml, - ParserState->AmlStart); - WalkState->Opcode = AcpiPsPeekOpcode (ParserState); +/******************************************************************************* + * + * FUNCTION: AcpiPsBuildNamedOp + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Begin of named Op in AML + * UnnamedOp - Early Op (not a named Op) + * Op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); - switch (WalkState->OpInfo->Class) - { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - WalkState->Opcode = AML_INT_NAMEPATH_OP; - WalkState->ArgTypes = ARGP_NAMESTRING; - break; +static ACPI_STATUS +AcpiPsBuildNamedOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *UnnamedOp, + ACPI_PARSE_OBJECT **Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Arg = NULL; - case AML_CLASS_UNKNOWN: - /* The opcode is unrecognized. Just skip unknown opcodes */ + ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Found unknown opcode %X at AML address %p offset %X, ignoring\n", - WalkState->Opcode, ParserState->Aml, WalkState->AmlOffset)); - ACPI_DUMP_BUFFER (ParserState->Aml, 128); + UnnamedOp->Common.Value.Arg = NULL; + UnnamedOp->Common.ArgListLength = 0; + UnnamedOp->Common.AmlOpcode = WalkState->Opcode; - /* Assume one-byte bad opcode */ + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && + (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) + { + Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } - ParserState->Aml++; - continue; + AcpiPsAppendArg (UnnamedOp, Arg); + INCREMENT_ARG_LIST (WalkState->ArgTypes); + } - default: + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } - /* Found opcode info, this is a normal opcode */ + /* We know that this arg is a name, move to next arg */ - ParserState->Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); - WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; - break; - } + INCREMENT_ARG_LIST (WalkState->ArgTypes); - /* Create Op structure and append to parent's argument list */ + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + WalkState->Op = NULL; - if (WalkState->OpInfo->Flags & AML_NAMED) - { - /* Allocate a new PreOp if necessary */ + Status = WalkState->DescendingCallback (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); + return_ACPI_STATUS (Status); + } - if (!PreOp) - { - PreOp = AcpiPsAllocOp (WalkState->Opcode); - if (!PreOp) - { - Status = AE_NO_MEMORY; - goto CloseThisOp; - } - } + if (!*Op) + { + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + } - PreOp->Common.Value.Arg = NULL; - PreOp->Common.AmlOpcode = WalkState->Opcode; + Status = AcpiPsNextParseState (WalkState, *Op, Status); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_PENDING) + { + return_ACPI_STATUS (AE_CTRL_PARSE_PENDING); + } + return_ACPI_STATUS (Status); + } - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && - (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) - { - Status = AcpiPsGetNextArg (WalkState, ParserState, - GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); - if (ACPI_FAILURE (Status)) - { - goto CloseThisOp; - } + AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); + AcpiGbl_Depth++; - AcpiPsAppendArg (PreOp, Arg); - INCREMENT_ARG_LIST (WalkState->ArgTypes); - } + if ((*Op)->Common.AmlOpcode == AML_REGION_OP) + { + /* + * Defer final parsing of an OperationRegion body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the TermArg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*Op)->Named.Data = AmlOpStart; + (*Op)->Named.Length = 0; + } - /* - * Make sure that we found a NAME and didn't run out of - * arguments - */ - if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) - { - Status = AE_AML_NO_OPERAND; - goto CloseThisOp; - } + return_ACPI_STATUS (AE_OK); +} - /* We know that this arg is a name, move to next arg */ - INCREMENT_ARG_LIST (WalkState->ArgTypes); +/******************************************************************************* + * + * FUNCTION: AcpiPsCreateOp + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Op start in AML + * NewOp - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - WalkState->Op = NULL; +static ACPI_STATUS +AcpiPsCreateOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT **NewOp) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Op; + ACPI_PARSE_OBJECT *NamedOp = NULL; + ACPI_PARSE_OBJECT *ParentScope; + UINT8 ArgumentCount; + const ACPI_OPCODE_INFO *OpInfo; - Status = WalkState->DescendingCallback (WalkState, &Op); - if (ACPI_FAILURE (Status)) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "During name lookup/catalog, %s\n", - AcpiFormatException (Status))); - goto CloseThisOp; - } - if (!Op) - { - continue; - } + ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); - Status = AcpiPsNextParseState (WalkState, Op, Status); - if (Status == AE_CTRL_PENDING) - { - Status = AE_OK; - goto CloseThisOp; - } - if (ACPI_FAILURE (Status)) - { - goto CloseThisOp; - } + Status = AcpiPsGetAmlOpcode (WalkState); + if (Status == AE_CTRL_PARSE_CONTINUE) + { + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + } - AcpiPsAppendArg (Op, PreOp->Common.Value.Arg); - AcpiGbl_Depth++; + /* Create Op structure and append to parent's argument list */ - if (Op->Common.AmlOpcode == AML_REGION_OP) - { - /* - * Defer final parsing of an OperationRegion body, - * because we don't have enough info in the first pass - * to parse it correctly (i.e., there may be method - * calls within the TermArg elements of the body.) - * - * However, we must continue parsing because - * the opregion is not a standalone package -- - * we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - Op->Named.Data = AmlOpStart; - Op->Named.Length = 0; - } - } - else - { - /* Not a named opcode, just allocate Op and append to parent */ + WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } - WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); - Op = AcpiPsAllocOp (WalkState->Opcode); - if (!Op) - { - Status = AE_NO_MEMORY; - goto CloseThisOp; - } + if (WalkState->OpInfo->Flags & AML_NAMED) + { + Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); + AcpiPsFreeOp (Op); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } - if (WalkState->OpInfo->Flags & AML_CREATE) - { - /* - * Backup to beginning of CreateXXXfield declaration - * BodyLength is unknown until we parse the body - */ - Op->Named.Data = AmlOpStart; - Op->Named.Length = 0; - } + *NewOp = NamedOp; + return_ACPI_STATUS (AE_OK); + } - AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op); + /* Not a named opcode, just allocate Op and append to parent */ - if ((WalkState->DescendingCallback != NULL)) - { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - WalkState->Op = Op; - - Status = WalkState->DescendingCallback (WalkState, &Op); - Status = AcpiPsNextParseState (WalkState, Op, Status); - if (Status == AE_CTRL_PENDING) - { - Status = AE_OK; - goto CloseThisOp; - } - - if (ACPI_FAILURE (Status)) - { - goto CloseThisOp; - } - } - } + if (WalkState->OpInfo->Flags & AML_CREATE) + { + /* + * Backup to beginning of CreateXXXfield declaration + * BodyLength is unknown until we parse the body + */ + Op->Named.Data = AmlOpStart; + Op->Named.Length = 0; + } - Op->Common.AmlOffset = WalkState->AmlOffset; + ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); + AcpiPsAppendArg (ParentScope, Op); - if (WalkState->OpInfo) + if (ParentScope) + { + OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); + if (OpInfo->Flags & AML_HAS_TARGET) + { + ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); + if (ParentScope->Common.ArgListLength > ArgumentCount) { - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", - (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, - Op, ParserState->Aml, Op->Common.AmlOffset)); + Op->Common.Flags |= ACPI_PARSEOP_TARGET; } } + else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) + { + Op->Common.Flags |= ACPI_PARSEOP_TARGET; + } + } - + if (WalkState->DescendingCallback != NULL) + { /* - * Start ArgCount at zero because we don't know if there are - * any args yet + * Find the object. This will either insert the object into + * the namespace or simply look it up */ - WalkState->ArgCount = 0; + WalkState->Op = *NewOp = Op; - /* Are there any arguments that must be processed? */ - - if (WalkState->ArgTypes) + Status = WalkState->DescendingCallback (WalkState, &Op); + Status = AcpiPsNextParseState (WalkState, Op, Status); + if (Status == AE_CTRL_PENDING) { - /* Get arguments */ - - switch (Op->Common.AmlOpcode) - { - case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ - case AML_WORD_OP: /* AML_WORDDATA_ARG */ - case AML_DWORD_OP: /* AML_DWORDATA_ARG */ - case AML_QWORD_OP: /* AML_QWORDATA_ARG */ - case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ - - /* Fill in constant or string argument directly */ + Status = AE_CTRL_PARSE_PENDING; + } + } - AcpiPsGetNextSimpleArg (ParserState, - GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); - break; + return_ACPI_STATUS (Status); +} - case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ - Status = AcpiPsGetNextNamepath (WalkState, ParserState, Op, 1); - if (ACPI_FAILURE (Status)) - { - goto CloseThisOp; - } +/******************************************************************************* + * + * FUNCTION: AcpiPsGetArguments + * + * PARAMETERS: WalkState - Current state + * AmlOpStart - Op start in AML + * Op - Current Op + * + * RETURN: Status + * + * DESCRIPTION: Get arguments for passed Op. + * + ******************************************************************************/ - WalkState->ArgTypes = 0; - break; +static ACPI_STATUS +AcpiPsGetArguments ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *Op) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Arg = NULL; - default: - /* - * Op is not a constant or string, append each argument - * to the Op - */ - while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && - !WalkState->ArgCount) - { - WalkState->AmlOffset = (UINT32) - ACPI_PTR_DIFF (ParserState->Aml, ParserState->AmlStart); - Status = AcpiPsGetNextArg (WalkState, ParserState, - GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), - &Arg); - if (ACPI_FAILURE (Status)) - { - goto CloseThisOp; - } + ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); - if (Arg) - { - Arg->Common.AmlOffset = WalkState->AmlOffset; - AcpiPsAppendArg (Op, Arg); - } - INCREMENT_ARG_LIST (WalkState->ArgTypes); - } + switch (Op->Common.AmlOpcode) + { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_QWORD_OP: /* AML_QWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ - /* Special processing for certain opcodes */ + /* Fill in constant or string argument directly */ - /* TBD (remove): Temporary mechanism to disable this code if needed */ + AcpiPsGetNextSimpleArg (&(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); + break; -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ - if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS1) && - ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0)) - { - /* - * We want to skip If/Else/While constructs during Pass1 - * because we want to actually conditionally execute the - * code during Pass2. - * - * Except for disassembly, where we always want to - * walk the If/Else/While packages - */ - switch (Op->Common.AmlOpcode) - { - case AML_IF_OP: - case AML_ELSE_OP: - case AML_WHILE_OP: + Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Pass1: Skipping an If/Else/While body\n")); + WalkState->ArgTypes = 0; + break; - /* Skip body of if/else/while in pass 1 */ + default: + /* + * Op is not a constant or string, append each argument to the Op + */ + while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) + { + WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, + WalkState->ParserState.AmlStart); - ParserState->Aml = ParserState->PkgEnd; - WalkState->ArgCount = 0; - break; + Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } - default: - break; - } - } -#endif - switch (Op->Common.AmlOpcode) - { - case AML_METHOD_OP: - - /* - * Skip parsing of control method - * because we don't have enough info in the first pass - * to parse it correctly. - * - * Save the length and address of the body - */ - Op->Named.Data = ParserState->Aml; - Op->Named.Length = (UINT32) (ParserState->PkgEnd - - ParserState->Aml); - - /* Skip body of method */ - - ParserState->Aml = ParserState->PkgEnd; - WalkState->ArgCount = 0; - break; - - case AML_BUFFER_OP: - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - if ((Op->Common.Parent) && - (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && - (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) - { - /* - * Skip parsing of Buffers and Packages - * because we don't have enough info in the first pass - * to parse them correctly. - */ - Op->Named.Data = AmlOpStart; - Op->Named.Length = (UINT32) (ParserState->PkgEnd - - AmlOpStart); - - /* Skip body */ - - ParserState->Aml = ParserState->PkgEnd; - WalkState->ArgCount = 0; - } - break; + if (Arg) + { + Arg->Common.AmlOffset = WalkState->AmlOffset; + AcpiPsAppendArg (Op, Arg); + } - case AML_WHILE_OP: + INCREMENT_ARG_LIST (WalkState->ArgTypes); + } - if (WalkState->ControlState) - { - WalkState->ControlState->Control.PackageEnd = - ParserState->PkgEnd; - } - break; - default: + /* Special processing for certain opcodes */ - /* No action for all other opcodes */ - break; - } - break; - } - } + /* TBD (remove): Temporary mechanism to disable this code if needed */ - /* Check for arguments that need to be processed */ +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - if (WalkState->ArgCount) + if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS1) && + ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0)) { /* - * There are arguments (complex ones), push Op and - * prepare for argument + * We want to skip If/Else/While constructs during Pass1 because we + * want to actually conditionally execute the code during Pass2. + * + * Except for disassembly, where we always want to walk the + * If/Else/While packages */ - Status = AcpiPsPushScope (ParserState, Op, - WalkState->ArgTypes, WalkState->ArgCount); - if (ACPI_FAILURE (Status)) + switch (Op->Common.AmlOpcode) { - goto CloseThisOp; - } - Op = NULL; - continue; - } + case AML_IF_OP: + case AML_ELSE_OP: + case AML_WHILE_OP: - /* - * All arguments have been processed -- Op is complete, - * prepare for next - */ - WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); - if (WalkState->OpInfo->Flags & AML_NAMED) - { - if (AcpiGbl_Depth) - { - AcpiGbl_Depth--; - } + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Pass1: Skipping an If/Else/While body\n")); - if (Op->Common.AmlOpcode == AML_REGION_OP) - { - /* - * Skip parsing of control method or opregion body, - * because we don't have enough info in the first pass - * to parse them correctly. - * - * Completed parsing an OpRegion declaration, we now - * know the length. - */ - Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + /* Skip body of if/else/while in pass 1 */ + + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; + break; + + default: + break; } } +#endif - if (WalkState->OpInfo->Flags & AML_CREATE) + switch (Op->Common.AmlOpcode) { + case AML_METHOD_OP: /* - * Backup to beginning of CreateXXXfield declaration (1 for - * Opcode) + * Skip parsing of control method because we don't have enough + * info in the first pass to parse it correctly. * - * BodyLength is unknown until we parse the body + * Save the length and address of the body */ - Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); - } + Op->Named.Data = WalkState->ParserState.Aml; + Op->Named.Length = (UINT32) + (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); - /* This op complete, notify the dispatcher */ + /* Skip body of method */ - if (WalkState->AscendingCallback != NULL) - { - WalkState->Op = Op; - WalkState->Opcode = Op->Common.AmlOpcode; + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; + break; - Status = WalkState->AscendingCallback (WalkState); - Status = AcpiPsNextParseState (WalkState, Op, Status); - if (Status == AE_CTRL_PENDING) + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if ((Op->Common.Parent) && + (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && + (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) { - Status = AE_OK; - goto CloseThisOp; + /* + * Skip parsing of Buffers and Packages because we don't have + * enough info in the first pass to parse them correctly. + */ + Op->Named.Data = AmlOpStart; + Op->Named.Length = (UINT32) + (WalkState->ParserState.PkgEnd - AmlOpStart); + + /* Skip body */ + + WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; + WalkState->ArgCount = 0; } - } + break; + case AML_WHILE_OP: -CloseThisOp: - /* - * Finished one argument of the containing scope - */ - ParserState->Scope->ParseScope.ArgCount--; + if (WalkState->ControlState) + { + WalkState->ControlState->Control.PackageEnd = + WalkState->ParserState.PkgEnd; + } + break; - /* Finished with PreOp */ + default: - if (PreOp) - { - AcpiPsFreeOp (PreOp); - PreOp = NULL; + /* No action for all other opcodes */ + break; } - /* Close this Op (will result in parse subtree deletion) */ + break; + } - Status2 = AcpiPsCompleteThisOp (WalkState, Op); - if (ACPI_FAILURE (Status2)) - { - return_ACPI_STATUS (Status2); - } - Op = NULL; + return_ACPI_STATUS (AE_OK); +} - switch (Status) - { - case AE_OK: - break; +/******************************************************************************* + * + * FUNCTION: AcpiPsCompleteOp + * + * PARAMETERS: WalkState - Current state + * Op - Returned Op + * Status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ - case AE_CTRL_TRANSFER: +static ACPI_STATUS +AcpiPsCompleteOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **Op, + ACPI_STATUS Status) +{ + ACPI_STATUS Status2; - /* We are about to transfer to a called method. */ - WalkState->PrevOp = Op; - WalkState->PrevArgTypes = WalkState->ArgTypes; - return_ACPI_STATUS (Status); + ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); - case AE_CTRL_END: + /* + * Finished one argument of the containing scope + */ + WalkState->ParserState.Scope->ParseScope.ArgCount--; - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); + /* Close this Op (will result in parse subtree deletion) */ - if (Op) - { - WalkState->Op = Op; - WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); - WalkState->Opcode = Op->Common.AmlOpcode; + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } - Status = WalkState->AscendingCallback (WalkState); - Status = AcpiPsNextParseState (WalkState, Op, Status); + *Op = NULL; - Status2 = AcpiPsCompleteThisOp (WalkState, Op); - if (ACPI_FAILURE (Status2)) - { - return_ACPI_STATUS (Status2); - } - Op = NULL; - } - Status = AE_OK; - break; + switch (Status) + { + case AE_OK: + break; - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: + case AE_CTRL_TRANSFER: - /* Pop off scopes until we find the While */ + /* We are about to transfer to a called method */ - while (!Op || (Op->Common.AmlOpcode != AML_WHILE_OP)) - { - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); - } + WalkState->PrevOp = NULL; + WalkState->PrevArgTypes = WalkState->ArgTypes; + return_ACPI_STATUS (Status); - /* Close this iteration of the While loop */ - WalkState->Op = Op; - WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); - WalkState->Opcode = Op->Common.AmlOpcode; + case AE_CTRL_END: + + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + + if (*Op) + { + WalkState->Op = *Op; + WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); + WalkState->Opcode = (*Op)->Common.AmlOpcode; Status = WalkState->AscendingCallback (WalkState); - Status = AcpiPsNextParseState (WalkState, Op, Status); + Status = AcpiPsNextParseState (WalkState, *Op, Status); - Status2 = AcpiPsCompleteThisOp (WalkState, Op); + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); if (ACPI_FAILURE (Status2)) { return_ACPI_STATUS (Status2); } - Op = NULL; + } - Status = AE_OK; - break; + Status = AE_OK; + break; - case AE_CTRL_TERMINATE: + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: - Status = AE_OK; + /* Pop off scopes until we find the While */ - /* Clean up */ - do - { - if (Op) - { - Status2 = AcpiPsCompleteThisOp (WalkState, Op); - if (ACPI_FAILURE (Status2)) - { - return_ACPI_STATUS (Status2); - } - } - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); + while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) + { + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + } - } while (Op); + /* Close this iteration of the While loop */ - return_ACPI_STATUS (Status); + WalkState->Op = *Op; + WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); + WalkState->Opcode = (*Op)->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, *Op, Status); + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } - default: /* All other non-AE_OK status */ + Status = AE_OK; + break; - do + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do + { + if (*Op) { - if (Op) + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) { - Status2 = AcpiPsCompleteThisOp (WalkState, Op); - if (ACPI_FAILURE (Status2)) - { - return_ACPI_STATUS (Status2); - } + return_ACPI_STATUS (Status2); } - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); - } while (Op); + AcpiUtDeleteGenericState ( + AcpiUtPopGenericState (&WalkState->ControlState)); + } + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); - /* - * TBD: Cleanup parse ops on error - */ -#if 0 - if (Op == NULL) + } while (*Op); + + return_ACPI_STATUS (AE_OK); + + + default: /* All other non-AE_OK status */ + + do + { + if (*Op) { - AcpiPsPopScope (ParserState, &Op, - &WalkState->ArgTypes, &WalkState->ArgCount); + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } } -#endif - WalkState->PrevOp = Op; - WalkState->PrevArgTypes = WalkState->ArgTypes; - return_ACPI_STATUS (Status); - } - /* This scope complete? */ + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); - if (AcpiPsHasCompletedScope (ParserState)) + } while (*Op); + + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*Op == NULL) { - AcpiPsPopScope (ParserState, &Op, + AcpiPsPopScope (ParserState, Op, &WalkState->ArgTypes, &WalkState->ArgCount); - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); - } - else - { - Op = NULL; } +#endif + WalkState->PrevOp = NULL; + WalkState->PrevArgTypes = WalkState->ArgTypes; + return_ACPI_STATUS (Status); + } - } /* while ParserState->Aml */ + /* This scope complete? */ + + if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) + { + AcpiPsPopScope (&(WalkState->ParserState), Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); + } + else + { + *Op = NULL; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsCompleteFinalOp + * + * PARAMETERS: WalkState - Current state + * Op - Current Op + * Status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status) +{ + ACPI_STATUS Status2; + + + ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); /* * Complete the last Op (if not completed), and clear the scope stack. * It is easily possible to end an AML "package" with an unbounded number * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. + * sequential closing braces). We want to terminate each one cleanly. */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); do @@ -864,7 +875,7 @@ CloseThisOp: { if (WalkState->AscendingCallback != NULL) { - WalkState->Op = Op; + WalkState->Op = Op; WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); WalkState->Opcode = Op->Common.AmlOpcode; @@ -872,8 +883,11 @@ CloseThisOp: Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { - Status = AE_OK; - goto CloseThisOp; + Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } } if (Status == AE_CTRL_TERMINATE) @@ -892,7 +906,7 @@ CloseThisOp: } } - AcpiPsPopScope (ParserState, &Op, + AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, &WalkState->ArgCount); } while (Op); @@ -916,7 +930,7 @@ CloseThisOp: } } - AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, + AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, &WalkState->ArgCount); } while (Op); @@ -925,3 +939,248 @@ CloseThisOp: } +/******************************************************************************* + * + * FUNCTION: AcpiPsParseLoop + * + * PARAMETERS: WalkState - Current state + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsParseLoop ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PARSE_OBJECT *Op = NULL; /* current op */ + ACPI_PARSE_STATE *ParserState; + UINT8 *AmlOpStart = NULL; + + + ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); + + + if (WalkState->DescendingCallback == NULL) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + ParserState = &WalkState->ParserState; + WalkState->ArgTypes = 0; + +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) + { + /* We are restarting a preempted control method */ + + if (AcpiPsHasCompletedScope (ParserState)) + { + /* + * We must check if a predicate to an IF or WHILE statement + * was just completed + */ + if ((ParserState->Scope->ParseScope.Op) && + ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || + (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && + (WalkState->ControlState) && + (WalkState->ControlState->Common.State == + ACPI_CONTROL_PREDICATE_EXECUTING)) + { + /* + * A predicate was just completed, get the value of the + * predicate and branch based on that value + */ + WalkState->Op = NULL; + Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); + if (ACPI_FAILURE (Status) && + ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) + { + if (Status == AE_AML_NO_RETURN_VALUE) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Invoked method did not return a value")); + + } + + ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed")); + return_ACPI_STATUS (Status); + } + + Status = AcpiPsNextParseState (WalkState, Op, Status); + } + + AcpiPsPopScope (ParserState, &Op, + &WalkState->ArgTypes, &WalkState->ArgCount); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); + } + else if (WalkState->PrevOp) + { + /* We were in the middle of an op */ + + Op = WalkState->PrevOp; + WalkState->ArgTypes = WalkState->PrevArgTypes; + } + } +#endif + + /* Iterative parsing loop, while there is more AML to process: */ + + while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) + { + AmlOpStart = ParserState->Aml; + if (!Op) + { + Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_PARSE_CONTINUE) + { + continue; + } + + if (Status == AE_CTRL_PARSE_PENDING) + { + Status = AE_OK; + } + + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + + Op->Common.AmlOffset = WalkState->AmlOffset; + + if (WalkState->OpInfo) + { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", + (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, + Op, ParserState->Aml, Op->Common.AmlOffset)); + } + } + + + /* + * Start ArgCount at zero because we don't know if there are + * any args yet + */ + WalkState->ArgCount = 0; + + /* Are there any arguments that must be processed? */ + + if (WalkState->ArgTypes) + { + /* Get arguments */ + + Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op); + if (ACPI_FAILURE (Status)) + { + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + } + + /* Check for arguments that need to be processed */ + + if (WalkState->ArgCount) + { + /* + * There are arguments (complex ones), push Op and + * prepare for argument + */ + Status = AcpiPsPushScope (ParserState, Op, + WalkState->ArgTypes, WalkState->ArgCount); + if (ACPI_FAILURE (Status)) + { + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + continue; + } + + Op = NULL; + continue; + } + + /* + * All arguments have been processed -- Op is complete, + * prepare for next + */ + WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); + if (WalkState->OpInfo->Flags & AML_NAMED) + { + if (AcpiGbl_Depth) + { + AcpiGbl_Depth--; + } + + if (Op->Common.AmlOpcode == AML_REGION_OP) + { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an OpRegion declaration, we now + * know the length. + */ + Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + } + } + + if (WalkState->OpInfo->Flags & AML_CREATE) + { + /* + * Backup to beginning of CreateXXXfield declaration (1 for + * Opcode) + * + * BodyLength is unknown until we parse the body + */ + Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); + } + + /* This op complete, notify the dispatcher */ + + if (WalkState->AscendingCallback != NULL) + { + WalkState->Op = Op; + WalkState->Opcode = Op->Common.AmlOpcode; + + Status = WalkState->AscendingCallback (WalkState); + Status = AcpiPsNextParseState (WalkState, Op, Status); + if (Status == AE_CTRL_PENDING) + { + Status = AE_OK; + } + } + + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + } /* while ParserState->Aml */ + + Status = AcpiPsCompleteFinalOp (WalkState, Op, Status); + return_ACPI_STATUS (Status); +} + |