static ACPI_STATUS AcpiPsGetAmlOpcode ( ACPI_WALK_STATE *WalkState) { ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); 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) { 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; case AML_CLASS_UNKNOWN: /* The opcode is unrecognized. Just skip unknown opcodes */ ACPI_ERROR ((AE_INFO, "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring", WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset)); ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128); /* Assume one-byte bad opcode */ WalkState->ParserState.Aml++; return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); default: /* Found opcode info, this is a normal opcode */ WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; break; } return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiPsGetAmlOpcode ( ACPI_WALK_STATE *WalkState) { ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); 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) { 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; case AML_CLASS_UNKNOWN: /* The opcode is unrecognized. Complain and skip unknown opcodes */ if (WalkState->PassNumber == 2) { ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", WalkState->Opcode, (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)))); ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48); #ifdef ACPI_ASL_COMPILER /* * This is executed for the disassembler only. Output goes * to the disassembled ASL output file. */ AcpiOsPrintf ( "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", WalkState->Opcode, (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))); /* Dump the context surrounding the invalid opcode */ AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16), 48, DB_BYTE_DISPLAY, (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); AcpiOsPrintf (" */\n"); #endif } /* Increment past one-byte or two-byte opcode */ WalkState->ParserState.Aml++; if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */ { WalkState->ParserState.Aml++; } return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); default: /* Found opcode info, this is a normal opcode */ WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; break; } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiPsParseLoop ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_PARSE_OBJECT *Op = NULL; /* current op */ const ACPI_OPCODE_INFO *OpInfo; ACPI_PARSE_OBJECT *Arg = NULL; ACPI_PARSE2_OBJECT *DeferredOp; UINT32 ArgCount; /* push for fixed or var args */ UINT32 ArgTypes = 0; UINT32 AmlOffset; UINT16 Opcode; ACPI_PARSE_OBJECT PreOp; ACPI_PARSE_STATE *ParserState; UINT8 *AmlOpStart; FUNCTION_TRACE_PTR ("PsParseLoop", WalkState); ParserState = WalkState->ParserState; #ifndef PARSER_ONLY if (WalkState->WalkType & 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->Opcode == AML_IF_OP) || (ParserState->Scope->ParseScope.Op->Opcode == AML_WHILE_OP)) && (WalkState->ControlState) && (WalkState->ControlState->Common.State == CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the * predicate and branch based on that value */ Status = AcpiDsGetPredicateValue (WalkState, NULL, 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_DEBUG_PRINT ((ACPI_DB_ERROR, "GetPredicate Failed, %s\n", AcpiFormatException (Status))); return_ACPI_STATUS (Status); } Status = AcpiPsNextParseState (WalkState, Op, Status); } AcpiPsPopScope (ParserState, &Op, &ArgTypes, &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; ArgTypes = WalkState->PrevArgTypes; } } #endif /* * Iterative parsing loop, while there is more aml to process: */ while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) { if (!Op) { /* Get the next opcode from the AML stream */ AmlOpStart = ParserState->Aml; AmlOffset = ParserState->Aml - ParserState->AmlStart; Opcode = AcpiPsPeekOpcode (ParserState); /* * First cut to determine what we have found: * 1) A valid AML opcode * 2) A name string * 3) An unknown/invalid opcode */ OpInfo = AcpiPsGetOpcodeInfo (Opcode); switch (ACPI_GET_OP_TYPE (OpInfo)) { case ACPI_OP_TYPE_OPCODE: /* Found opcode info, this is a normal opcode */ ParserState->Aml += AcpiPsGetOpcodeSize (Opcode); ArgTypes = OpInfo->ParseArgs; break; case ACPI_OP_TYPE_ASCII: case ACPI_OP_TYPE_PREFIX: /* * Starts with a valid prefix or ASCII char, this is a name * string. Convert the bare name string to a namepath. */ Opcode = AML_INT_NAMEPATH_OP; ArgTypes = ARGP_NAMESTRING; break; case ACPI_OP_TYPE_UNKNOWN: /* The opcode is unrecognized. Just skip unknown opcodes */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found unknown opcode %lX at AML offset %X, ignoring\n", Opcode, AmlOffset)); DUMP_BUFFER (ParserState->Aml, 128); /* Assume one-byte bad opcode */ ParserState->Aml++; continue; } /* Create Op structure and append to parent's argument list */ if (OpInfo->Flags & AML_NAMED) { PreOp.Value.Arg = NULL; PreOp.Opcode = Opcode; while (GET_CURRENT_ARG_TYPE (ArgTypes) != ARGP_NAME) { Arg = AcpiPsGetNextArg (ParserState, GET_CURRENT_ARG_TYPE (ArgTypes), &ArgCount); AcpiPsAppendArg (&PreOp, Arg); INCREMENT_ARG_LIST (ArgTypes); } /* We know that this arg is a name, move to next arg */ INCREMENT_ARG_LIST (ArgTypes); if (WalkState->DescendingCallback != NULL) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ Status = WalkState->DescendingCallback (Opcode, NULL, WalkState, &Op); if (Op == NULL) { continue; } Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { Status = AE_OK; goto CloseThisOp; } if (ACPI_FAILURE (Status)) { goto CloseThisOp; } } AcpiPsAppendArg (Op, PreOp.Value.Arg); AcpiGbl_Depth++; if (Op->Opcode == AML_REGION_OP) { DeferredOp = (ACPI_PARSE2_OBJECT *) 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) */ DeferredOp->Data = AmlOpStart; DeferredOp->Length = 0; } } else { /* Not a named opcode, just allocate Op and append to parent */ OpInfo = AcpiPsGetOpcodeInfo (Opcode); Op = AcpiPsAllocOp (Opcode); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } if (OpInfo->Flags & AML_CREATE) { /* * Backup to beginning of CreateXXXfield declaration * BodyLength is unknown until we parse the body */ DeferredOp = (ACPI_PARSE2_OBJECT *) Op; DeferredOp->Data = AmlOpStart; DeferredOp->Length = 0; } AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op); if ((WalkState->DescendingCallback != NULL)) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ Status = WalkState->DescendingCallback (Opcode, Op, WalkState, &Op); Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { Status = AE_OK; goto CloseThisOp; } if (ACPI_FAILURE (Status)) { goto CloseThisOp; } } } Op->AmlOffset = AmlOffset; if (OpInfo) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Op=%p Opcode=%4.4lX Aml %p Oft=%5.5lX\n", Op, Op->Opcode, ParserState->Aml, Op->AmlOffset)); } } /* Start ArgCount at zero because we don't know if there are any args yet */ ArgCount = 0; if (ArgTypes) /* Are there any arguments that must be processed? */ { /* get arguments */ switch (Op->Opcode) { 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 */ AcpiPsGetNextSimpleArg (ParserState, GET_CURRENT_ARG_TYPE (ArgTypes), Op); break; case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ AcpiPsGetNextNamepath (ParserState, Op, &ArgCount, 1); ArgTypes = 0; break; default: /* Op is not a constant or string, append each argument */ while (GET_CURRENT_ARG_TYPE (ArgTypes) && !ArgCount) { AmlOffset = ParserState->Aml - ParserState->AmlStart; Arg = AcpiPsGetNextArg (ParserState, GET_CURRENT_ARG_TYPE (ArgTypes), &ArgCount); if (Arg) { Arg->AmlOffset = AmlOffset; AcpiPsAppendArg (Op, Arg); } INCREMENT_ARG_LIST (ArgTypes); } /* For a method, save the length and address of the body */ if (Op->Opcode == AML_METHOD_OP) { DeferredOp = (ACPI_PARSE2_OBJECT *) Op; /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass * to parse them correctly. */ DeferredOp->Data = ParserState->Aml; DeferredOp->Length = (UINT32) (ParserState->PkgEnd - ParserState->Aml); /* * Skip body of method. For OpRegions, we must continue * parsing because the opregion is not a standalone * package (We don't know where the end is). */ ParserState->Aml = ParserState->PkgEnd; ArgCount = 0; } break; } } /* * Zero ArgCount means that all arguments for this op have been processed */ if (!ArgCount) { /* completed Op, prepare for next */ OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); if (OpInfo->Flags & AML_NAMED) { if (AcpiGbl_Depth) { AcpiGbl_Depth--; } if (Op->Opcode == AML_REGION_OP) { DeferredOp = (ACPI_PARSE2_OBJECT *) 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. */ DeferredOp->Length = (UINT32) (ParserState->Aml - DeferredOp->Data); } } if (OpInfo->Flags & AML_CREATE) { /* * Backup to beginning of CreateXXXfield declaration (1 for * Opcode) * * BodyLength is unknown until we parse the body */ DeferredOp = (ACPI_PARSE2_OBJECT *) Op; DeferredOp->Length = (UINT32) (ParserState->Aml - DeferredOp->Data); } /* This op complete, notify the dispatcher */ if (WalkState->AscendingCallback != NULL) { Status = WalkState->AscendingCallback (WalkState, Op); Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { Status = AE_OK; goto CloseThisOp; } } CloseThisOp: /* * Finished one argument of the containing scope */ ParserState->Scope->ParseScope.ArgCount--; /* Close this Op (may result in parse subtree deletion) */ if (AcpiPsCompleteThisOp (WalkState, Op)) { Op = NULL; } switch (Status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* * We are about to transfer to a called method. */ WalkState->PrevOp = Op; WalkState->PrevArgTypes = ArgTypes; return_ACPI_STATUS (Status); break; case AE_CTRL_END: AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); Status = WalkState->AscendingCallback (WalkState, Op); Status = AcpiPsNextParseState (WalkState, Op, Status); AcpiPsCompleteThisOp (WalkState, Op); Op = NULL; Status = AE_OK; break; case AE_CTRL_TERMINATE: Status = AE_OK; /* Clean up */ do { if (Op) { AcpiPsCompleteThisOp (WalkState, Op); } AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); } while (Op); return_ACPI_STATUS (Status); break; default: /* All other non-AE_OK status */ if (Op == NULL) { AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); } WalkState->PrevOp = Op; WalkState->PrevArgTypes = ArgTypes; /* * TEMP: */ return_ACPI_STATUS (Status); break; } /* This scope complete? */ if (AcpiPsHasCompletedScope (ParserState)) { AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); } else { Op = NULL; } } /* ArgCount is non-zero */ else { /* complex argument, push Op and prepare for argument */ AcpiPsPushScope (ParserState, Op, ArgTypes, ArgCount); Op = NULL; } } /* while ParserState->Aml */ /* * 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 AML blocks are closed with * sequential closing braces). We want to terminate each one cleanly. */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Package complete at Op %p\n", Op)); do { if (Op) { if (WalkState->AscendingCallback != NULL) { Status = WalkState->AscendingCallback (WalkState, Op); Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { Status = AE_OK; goto CloseThisOp; } if (Status == AE_CTRL_TERMINATE) { Status = AE_OK; /* Clean up */ do { if (Op) { AcpiPsCompleteThisOp (WalkState, Op); } AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); } while (Op); return_ACPI_STATUS (Status); } else if (ACPI_FAILURE (Status)) { AcpiPsCompleteThisOp (WalkState, Op); return_ACPI_STATUS (Status); } } AcpiPsCompleteThisOp (WalkState, Op); } AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); } while (Op); return_ACPI_STATUS (Status); }