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; ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); UnnamedOp->Common.Value.Arg = NULL; UnnamedOp->Common.ArgListLength = 0; UnnamedOp->Common.AmlOpcode = WalkState->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); } AcpiPsAppendArg (UnnamedOp, Arg); INCREMENT_ARG_LIST (WalkState->ArgTypes); } /* * 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); } /* We know that this arg is a name, move to next arg */ INCREMENT_ARG_LIST (WalkState->ArgTypes); /* * Find the object. This will either insert the object into * the namespace or simply look it up */ WalkState->Op = NULL; Status = WalkState->DescendingCallback (WalkState, Op); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); return_ACPI_STATUS (Status); } if (!*Op) { return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); } 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); } AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); AcpiGbl_Depth++; if ((*Op)->Common.AmlOpcode == AML_REGION_OP || (*Op)->Common.AmlOpcode == AML_DATA_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; } return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiPsGetArguments ( ACPI_WALK_STATE *WalkState, UINT8 *AmlOpStart, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status = AE_OK; ACPI_PARSE_OBJECT *Arg = NULL; const ACPI_OPCODE_INFO *OpInfo; ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); 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 */ AcpiPsGetNextSimpleArg (&(WalkState->ParserState), GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); break; case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } WalkState->ArgTypes = 0; break; 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); Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Arg) { Arg->Common.AmlOffset = WalkState->AmlOffset; AcpiPsAppendArg (Op, Arg); } INCREMENT_ARG_LIST (WalkState->ArgTypes); } /* * Handle executable code at "module-level". This refers to * executable opcodes that appear outside of any control method. */ if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) && ((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: /* * Currently supported module-level opcodes are: * IF/ELSE/WHILE. These appear to be the most common, * and easiest to support since they open an AML * package. */ if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) { AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart, (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart), WalkState->OwnerId); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); /* Skip body of if/else/while in pass 1 */ WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; WalkState->ArgCount = 0; break; default: /* * Check for an unsupported executable opcode at module * level. We must be in PASS1, the parent must be a SCOPE, * The opcode class must be EXECUTE, and the opcode must * not be an argument to another opcode. */ if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) && (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) { OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); if ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Arg)) { ACPI_WARNING ((AE_INFO, "Unsupported module-level executable opcode " "0x%.2X at table offset 0x%.4X", Op->Common.AmlOpcode, (UINT32) (ACPI_PTR_DIFF (AmlOpStart, WalkState->ParserState.AmlStart) + sizeof (ACPI_TABLE_HEADER)))); } } break; } } /* Special processing for certain opcodes */ 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 = WalkState->ParserState.Aml; Op->Named.Length = (UINT32) (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); /* Skip body of method */ WalkState->ParserState.Aml = WalkState->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) (WalkState->ParserState.PkgEnd - AmlOpStart); /* Skip body */ WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; WalkState->ArgCount = 0; } break; case AML_WHILE_OP: if (WalkState->ControlState) { WalkState->ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd; } break; default: /* No action for all other opcodes */ break; } break; } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AnOperandTypecheckWalkEnd ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { const ACPI_OPCODE_INFO *OpInfo; UINT32 RuntimeArgTypes; UINT32 RuntimeArgTypes2; UINT32 RequiredBtypes; UINT32 ThisNodeBtype; UINT32 CommonBtypes; UINT32 OpcodeClass; ACPI_PARSE_OBJECT *ArgOp; UINT32 ArgType; switch (Op->Asl.AmlOpcode) { case AML_RAW_DATA_BYTE: case AML_RAW_DATA_WORD: case AML_RAW_DATA_DWORD: case AML_RAW_DATA_QWORD: case AML_RAW_DATA_BUFFER: case AML_RAW_DATA_CHAIN: case AML_PACKAGE_LENGTH: case AML_UNASSIGNED_OPCODE: case AML_DEFAULT_ARG_OP: /* Ignore the internal (compiler-only) AML opcodes */ return (AE_OK); default: break; } OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); if (!OpInfo) { return (AE_OK); } ArgOp = Op->Asl.Child; OpcodeClass = OpInfo->Class; RuntimeArgTypes = OpInfo->RuntimeArgs; #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE /* * Update 11/2008: In practice, we can't perform this check. A simple * analysis is not sufficient. Also, it can cause errors when compiling * disassembled code because of the way Switch operators are implemented * (a While(One) loop with a named temp variable created within.) */ /* * If we are creating a named object, check if we are within a while loop * by checking if the parent is a WHILE op. This is a simple analysis, but * probably sufficient for many cases. * * Allow Scope(), Buffer(), and Package(). */ if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) { if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) { AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); } } #endif /* * Special case for control opcodes IF/RETURN/WHILE since they * have no runtime arg list (at this time) */ switch (Op->Asl.AmlOpcode) { case AML_IF_OP: case AML_WHILE_OP: case AML_RETURN_OP: if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) { /* Check for an internal method */ if (AnIsInternalMethod (ArgOp)) { return (AE_OK); } /* The lone arg is a method call, check it */ RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); if (Op->Asl.AmlOpcode == AML_RETURN_OP) { RequiredBtypes = 0xFFFFFFFF; } ThisNodeBtype = AnGetBtype (ArgOp); if (ThisNodeBtype == ACPI_UINT32_MAX) { return (AE_OK); } AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); } return (AE_OK); case AML_EXTERNAL_OP: /* * Not really a "runtime" opcode since it used by disassembler only. * The parser will find any issues with the operands. */ return (AE_OK); default: break; } /* Ignore the non-executable opcodes */ if (RuntimeArgTypes == ARGI_INVALID_OPCODE) { return (AE_OK); } /* * Special handling for certain opcodes. */ switch (Op->Asl.AmlOpcode) { /* BankField has one TermArg */ case AML_BANK_FIELD_OP: OpcodeClass = AML_CLASS_EXECUTE; ArgOp = ArgOp->Asl.Next; ArgOp = ArgOp->Asl.Next; break; /* Operation Region has 2 TermArgs */ case AML_REGION_OP: OpcodeClass = AML_CLASS_EXECUTE; ArgOp = ArgOp->Asl.Next; ArgOp = ArgOp->Asl.Next; break; /* DataTableRegion has 3 TermArgs */ case AML_DATA_REGION_OP: OpcodeClass = AML_CLASS_EXECUTE; ArgOp = ArgOp->Asl.Next; break; /* Buffers/Packages have a length that is a TermArg */ case AML_BUFFER_OP: case AML_PACKAGE_OP: case AML_VARIABLE_PACKAGE_OP: /* If length is a constant, we are done */ if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) || (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA)) { return (AE_OK); } break; /* Store can write any object to the Debug object */ case AML_STORE_OP: /* * If this is a Store() to the Debug object, we don't need * to perform any further validation -- because a Store of * any object to Debug is permitted and supported. */ if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP) { return (AE_OK); } break; default: break; } switch (OpcodeClass) { case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: case AML_CLASS_CONTROL: case AML_CLASS_RETURN_VALUE: /* Reverse the runtime argument list */ RuntimeArgTypes2 = 0; while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) { RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; RuntimeArgTypes2 |= ArgType; INCREMENT_ARG_LIST (RuntimeArgTypes); } /* Typecheck each argument */ while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) { /* Get the required type(s) for the argument */ RequiredBtypes = AnMapArgTypeToBtype (ArgType); if (!ArgOp) { AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, "Null ArgOp in argument loop"); AslAbort (); } /* Get the actual type of the argument */ ThisNodeBtype = AnGetBtype (ArgOp); if (ThisNodeBtype == ACPI_UINT32_MAX) { goto NextArgument; } /* Examine the arg based on the required type of the arg */ switch (ArgType) { case ARGI_TARGETREF: if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) { /* ZERO is the placeholder for "don't store result" */ ThisNodeBtype = RequiredBtypes; break; } /* Fallthrough */ case ARGI_STORE_TARGET: if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) { /* * This is the case where an original reference to a resource * descriptor field has been replaced by an (Integer) offset. * These named fields are supported at compile-time only; * the names are not passed to the interpreter (via the AML). */ if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) { AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); } else { AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); } } break; #ifdef __FUTURE_IMPLEMENTATION /* * Possible future typechecking support */ case ARGI_REFERENCE: /* References */ case ARGI_INTEGER_REF: case ARGI_OBJECT_REF: case ARGI_DEVICE_REF: switch (ArgOp->Asl.ParseOpcode) { case PARSEOP_LOCAL0: case PARSEOP_LOCAL1: case PARSEOP_LOCAL2: case PARSEOP_LOCAL3: case PARSEOP_LOCAL4: case PARSEOP_LOCAL5: case PARSEOP_LOCAL6: case PARSEOP_LOCAL7: /* TBD: implement analysis of current value (type) of the local */ /* For now, just treat any local as a typematch */ /*ThisNodeBtype = RequiredBtypes;*/ break; case PARSEOP_ARG0: case PARSEOP_ARG1: case PARSEOP_ARG2: case PARSEOP_ARG3: case PARSEOP_ARG4: case PARSEOP_ARG5: case PARSEOP_ARG6: /* Hard to analyze argument types, so we won't */ /* for now. Just treat any arg as a typematch */ /* ThisNodeBtype = RequiredBtypes; */ break; case PARSEOP_DEBUG: case PARSEOP_REFOF: case PARSEOP_INDEX: default: break; } break; #endif case ARGI_INTEGER: default: break; } /* Check for a type mismatch (required versus actual) */ CommonBtypes = ThisNodeBtype & RequiredBtypes; if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) { if (AnIsInternalMethod (ArgOp)) { return (AE_OK); } /* Check a method call for a valid return value */ AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); } /* * Now check if the actual type(s) match at least one * bit to the required type */ else if (!CommonBtypes) { /* No match -- this is a type mismatch error */ AnFormatBtype (StringBuffer, ThisNodeBtype); AnFormatBtype (StringBuffer2, RequiredBtypes); sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", StringBuffer, OpInfo->Name, StringBuffer2); AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); } NextArgument: ArgOp = ArgOp->Asl.Next; INCREMENT_ARG_LIST (RuntimeArgTypes2); } break; default: break; } return (AE_OK); }
acpi_status acpi_ps_build_named_op(struct acpi_walk_state *walk_state, u8 *aml_op_start, union acpi_parse_object *unnamed_op, union acpi_parse_object **op) { acpi_status status = AE_OK; union acpi_parse_object *arg = NULL; ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); unnamed_op->common.value.arg = NULL; unnamed_op->common.arg_list_length = 0; unnamed_op->common.aml_opcode = walk_state->opcode; /* * Get and append arguments until we find the node that contains * the name (the type ARGP_NAME). */ while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { ASL_CV_CAPTURE_COMMENTS(walk_state); status = acpi_ps_get_next_arg(walk_state, &(walk_state->parser_state), GET_CURRENT_ARG_TYPE(walk_state-> arg_types), &arg); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } acpi_ps_append_arg(unnamed_op, arg); INCREMENT_ARG_LIST(walk_state->arg_types); } /* are there any inline comments associated with the name_seg?? If so, save this. */ ASL_CV_CAPTURE_COMMENTS(walk_state); #ifdef ACPI_ASL_COMPILER if (acpi_gbl_current_inline_comment != NULL) { unnamed_op->common.name_comment = acpi_gbl_current_inline_comment; acpi_gbl_current_inline_comment = NULL; } #endif /* * Make sure that we found a NAME and didn't run out of arguments */ if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { return_ACPI_STATUS(AE_AML_NO_OPERAND); } /* We know that this arg is a name, move to next arg */ INCREMENT_ARG_LIST(walk_state->arg_types); /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = NULL; status = walk_state->descending_callback(walk_state, op); if (ACPI_FAILURE(status)) { if (status != AE_CTRL_TERMINATE) { ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); } return_ACPI_STATUS(status); } if (!*op) { return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); } status = acpi_ps_next_parse_state(walk_state, *op, status); if (ACPI_FAILURE(status)) { if (status == AE_CTRL_PENDING) { status = AE_CTRL_PARSE_PENDING; } return_ACPI_STATUS(status); } acpi_ps_append_arg(*op, unnamed_op->common.value.arg); #ifdef ACPI_ASL_COMPILER /* save any comments that might be associated with unnamed_op. */ (*op)->common.inline_comment = unnamed_op->common.inline_comment; (*op)->common.end_node_comment = unnamed_op->common.end_node_comment; (*op)->common.close_brace_comment = unnamed_op->common.close_brace_comment; (*op)->common.name_comment = unnamed_op->common.name_comment; (*op)->common.comment_list = unnamed_op->common.comment_list; (*op)->common.end_blk_comment = unnamed_op->common.end_blk_comment; (*op)->common.cv_filename = unnamed_op->common.cv_filename; (*op)->common.cv_parent_filename = unnamed_op->common.cv_parent_filename; (*op)->named.aml = unnamed_op->common.aml; unnamed_op->common.inline_comment = NULL; unnamed_op->common.end_node_comment = NULL; unnamed_op->common.close_brace_comment = NULL; unnamed_op->common.name_comment = NULL; unnamed_op->common.comment_list = NULL; unnamed_op->common.end_blk_comment = NULL; #endif if ((*op)->common.aml_opcode == AML_REGION_OP || (*op)->common.aml_opcode == AML_DATA_REGION_OP) { /* * Defer final parsing of an operation_region 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 term_arg 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 = aml_op_start; (*op)->named.length = 0; } return_ACPI_STATUS(AE_OK); }
ACPI_STATUS AcpiExResolveOperands ( UINT16 Opcode, ACPI_OPERAND_OBJECT **StackPtr, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status = AE_OK; UINT8 ObjectType; UINT32 ArgTypes; const ACPI_OPCODE_INFO *OpInfo; UINT32 ThisArgType; ACPI_OBJECT_TYPE TypeNeeded; UINT16 TargetOp = 0; ACPI_FUNCTION_TRACE_U32 (ExResolveOperands, Opcode); OpInfo = AcpiPsGetOpcodeInfo (Opcode); if (OpInfo->Class == AML_CLASS_UNKNOWN) { return_ACPI_STATUS (AE_AML_BAD_OPCODE); } ArgTypes = OpInfo->RuntimeArgs; if (ArgTypes == ARGI_INVALID_OPCODE) { ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", Opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", Opcode, OpInfo->Name, ArgTypes)); /* * Normal exit is with (ArgTypes == 0) at end of argument list. * Function will return an exception from within the loop upon * finding an entry which is not (or cannot be converted * to) the required type; if stack underflows; or upon * finding a NULL stack entry (which should not happen). */ while (GET_CURRENT_ARG_TYPE (ArgTypes)) { if (!StackPtr || !*StackPtr) { ACPI_ERROR ((AE_INFO, "Null stack entry at %p", StackPtr)); return_ACPI_STATUS (AE_AML_INTERNAL); } /* Extract useful items */ ObjDesc = *StackPtr; /* Decode the descriptor type */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_NAMED: /* Namespace Node */ ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; /* * Resolve an alias object. The construction of these objects * guarantees that there is only one level of alias indirection; * thus, the attached object is always the aliased namespace node */ if (ObjectType == ACPI_TYPE_LOCAL_ALIAS) { ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); *StackPtr = ObjDesc; ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; } break; case ACPI_DESC_TYPE_OPERAND: /* ACPI internal object */ ObjectType = ObjDesc->Common.Type; /* Check for bad ACPI_OBJECT_TYPE */ if (!AcpiUtValidObjectType (ObjectType)) { ACPI_ERROR ((AE_INFO, "Bad operand object type [0x%X]", ObjectType)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } if (ObjectType == (UINT8) ACPI_TYPE_LOCAL_REFERENCE) { /* Validate the Reference */ switch (ObjDesc->Reference.Class) { case ACPI_REFCLASS_DEBUG: TargetOp = AML_DEBUG_OP; /*lint -fallthrough */ case ACPI_REFCLASS_ARG: case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_INDEX: case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_TABLE: /* DdbHandle from LOAD_OP or LOAD_TABLE_OP */ case ACPI_REFCLASS_NAME: /* Reference to a named object */ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Operand is a Reference, Class [%s] %2.2X\n", AcpiUtGetReferenceName (ObjDesc), ObjDesc->Reference.Class)); break; default: ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X in %p", ObjDesc->Reference.Class, ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } break; default: /* Invalid descriptor */ ACPI_ERROR ((AE_INFO, "Invalid descriptor %p [%s]", ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Get one argument type, point to the next */ ThisArgType = GET_CURRENT_ARG_TYPE (ArgTypes); INCREMENT_ARG_LIST (ArgTypes); /* * Handle cases where the object does not need to be * resolved to a value */ switch (ThisArgType) { case ARGI_REF_OR_STRING: /* Can be a String or Reference */ if ((ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) && (ObjDesc->Common.Type == ACPI_TYPE_STRING)) { /* * String found - the string references a named object and * must be resolved to a node */ goto NextOperand; } /* * Else not a string - fall through to the normal Reference * case below */ /*lint -fallthrough */ case ARGI_REFERENCE: /* References: */ case ARGI_INTEGER_REF: case ARGI_OBJECT_REF: case ARGI_DEVICE_REF: case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ /* * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE * A Namespace Node is OK as-is */ if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) { goto NextOperand; } Status = AcpiExCheckObjectType (ACPI_TYPE_LOCAL_REFERENCE, ObjectType, ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } goto NextOperand; case ARGI_DATAREFOBJ: /* Store operator only */ /* * We don't want to resolve IndexOp reference objects during * a store because this would be an implicit DeRefOf operation. * Instead, we just want to store the reference object. * -- All others must be resolved below. */ if ((Opcode == AML_STORE_OP) && ((*StackPtr)->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && ((*StackPtr)->Reference.Class == ACPI_REFCLASS_INDEX)) { goto NextOperand; } break; default: /* All cases covered above */ break; } /* * Resolve this object to a value */ Status = AcpiExResolveToValue (StackPtr, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Get the resolved object */ ObjDesc = *StackPtr; /* * Check the resulting object (value) type */ switch (ThisArgType) { /* * For the simple cases, only one type of resolved object * is allowed */ case ARGI_MUTEX: /* Need an operand of type ACPI_TYPE_MUTEX */ TypeNeeded = ACPI_TYPE_MUTEX; break; case ARGI_EVENT: /* Need an operand of type ACPI_TYPE_EVENT */ TypeNeeded = ACPI_TYPE_EVENT; break; case ARGI_PACKAGE: /* Package */ /* Need an operand of type ACPI_TYPE_PACKAGE */ TypeNeeded = ACPI_TYPE_PACKAGE; break; case ARGI_ANYTYPE: /* Any operand type will do */ TypeNeeded = ACPI_TYPE_ANY; break; case ARGI_DDBHANDLE: /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ TypeNeeded = ACPI_TYPE_LOCAL_REFERENCE; break; /* * The more complex cases allow multiple resolved object types */ case ARGI_INTEGER: /* * Need an operand of type ACPI_TYPE_INTEGER, * But we can implicitly convert from a STRING or BUFFER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToInteger (ObjDesc, StackPtr, 16); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_BUFFER: /* * Need an operand of type ACPI_TYPE_BUFFER, * But we can implicitly convert from a STRING or INTEGER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_STRING: /* * Need an operand of type ACPI_TYPE_STRING, * But we can implicitly convert from a BUFFER or INTEGER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToString (ObjDesc, StackPtr, ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_COMPUTEDATA: /* Need an operand of type INTEGER, STRING or BUFFER */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_BUFFER_OR_STRING: /* Need an operand of type STRING or BUFFER */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; case ACPI_TYPE_INTEGER: /* Highest priority conversion is to type Buffer */ Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } break; default: ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_DATAOBJECT: /* * ARGI_DATAOBJECT is only used by the SizeOf operator. * Need a buffer, string, package, or RefOf reference. * * The only reference allowed here is a direct reference to * a namespace node. */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_LOCAL_REFERENCE: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Buffer/String/Package/Reference], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_COMPLEXOBJ: /* Need a buffer or package or (ACPI 2.0) String */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Buffer/String/Package], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_REGION: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Region/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_DATAREFOBJ: /* Used by the Store() operator only */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REFERENCE: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: case ACPI_TYPE_DDB_HANDLE: /* Valid operand */ break; default: if (AcpiGbl_EnableInterpreterSlack) { /* * Enable original behavior of Store(), allowing any and all * objects as the source operand. The ACPI spec does not * allow this, however. */ break; } if (TargetOp == AML_DEBUG_OP) { /* Allow store of any object to the Debug object */ break; } ACPI_ERROR ((AE_INFO, "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; default: /* Unknown type */ ACPI_ERROR ((AE_INFO, "Internal - Unknown ARGI (required operand) type 0x%X", ThisArgType)); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Make sure that the original object was resolved to the * required object type (Simple cases only). */ Status = AcpiExCheckObjectType (TypeNeeded, (*StackPtr)->Common.Type, *StackPtr); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } NextOperand: /* * If more operands needed, decrement StackPtr to point * to next operand on stack */ if (GET_CURRENT_ARG_TYPE (ArgTypes)) { StackPtr--; } } ACPI_DUMP_OPERANDS (WalkState->Operands, AcpiPsGetOpcodeName (Opcode), WalkState->NumOperands); return_ACPI_STATUS (Status); }
acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; acpi_status status2; union acpi_parse_object *op = NULL; /* current op */ union acpi_parse_object *arg = NULL; union acpi_parse_object *pre_op = NULL; struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state); if (walk_state->descending_callback == NULL) { return_ACPI_STATUS(AE_BAD_PARAMETER); } parser_state = &walk_state->parser_state; walk_state->arg_types = 0; #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { /* We are restarting a preempted control method */ if (acpi_ps_has_completed_scope(parser_state)) { /* * We must check if a predicate to an IF or WHILE statement * was just completed */ if ((parser_state->scope->parse_scope.op) && ((parser_state->scope->parse_scope.op->common. aml_opcode == AML_IF_OP) || (parser_state->scope->parse_scope.op->common. aml_opcode == AML_WHILE_OP)) && (walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the * predicate and branch based on that value */ walk_state->op = NULL; status = acpi_ds_get_predicate_value(walk_state, 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, "get_predicate Failed")); return_ACPI_STATUS(status); } status = acpi_ps_next_parse_state(walk_state, op, status); } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else if (walk_state->prev_op) { /* We were in the middle of an op */ op = walk_state->prev_op; walk_state->arg_types = walk_state->prev_arg_types; } } #endif /* Iterative parsing loop, while there is more AML to process: */ while ((parser_state->aml < parser_state->aml_end) || (op)) { aml_op_start = parser_state->aml; if (!op) { /* Get the next opcode from the AML stream */ walk_state->aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); walk_state->opcode = acpi_ps_peek_opcode(parser_state); /* * First cut to determine what we have found: * 1) A valid AML opcode * 2) A name string * 3) An unknown/invalid opcode */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); switch (walk_state->op_info->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. */ walk_state->opcode = AML_INT_NAMEPATH_OP; walk_state->arg_types = ARGP_NAMESTRING; break; case AML_CLASS_UNKNOWN: /* The opcode is unrecognized. Just skip unknown opcodes */ ACPI_ERROR((AE_INFO, "Found unknown opcode %X at AML address %p offset %X, ignoring", walk_state->opcode, parser_state->aml, walk_state->aml_offset)); ACPI_DUMP_BUFFER(parser_state->aml, 128); /* Assume one-byte bad opcode */ parser_state->aml++; continue; default: /* Found opcode info, this is a normal opcode */ parser_state->aml += acpi_ps_get_opcode_size(walk_state->opcode); walk_state->arg_types = walk_state->op_info->parse_args; break; } /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { /* Allocate a new pre_op if necessary */ if (!pre_op) { pre_op = acpi_ps_alloc_op(walk_state-> opcode); if (!pre_op) { status = AE_NO_MEMORY; goto close_this_op; } } pre_op->common.value.arg = NULL; pre_op->common.aml_opcode = walk_state->opcode; /* * Get and append arguments until we find the node that contains * the name (the type ARGP_NAME). */ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { status = acpi_ps_get_next_arg(walk_state, parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), &arg); if (ACPI_FAILURE(status)) { goto close_this_op; } acpi_ps_append_arg(pre_op, arg); INCREMENT_ARG_LIST(walk_state-> arg_types); } /* * Make sure that we found a NAME and didn't run out of * arguments */ if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { status = AE_AML_NO_OPERAND; goto close_this_op; } /* We know that this arg is a name, move to next arg */ INCREMENT_ARG_LIST(walk_state->arg_types); /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = NULL; status = walk_state->descending_callback(walk_state, &op); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); goto close_this_op; } if (!op) { continue; } status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } if (ACPI_FAILURE(status)) { goto close_this_op; } acpi_ps_append_arg(op, pre_op->common.value.arg); acpi_gbl_depth++; if (op->common.aml_opcode == AML_REGION_OP) { /* * Defer final parsing of an operation_region 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 term_arg 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 = aml_op_start; op->named.length = 0; } } else { /* Not a named opcode, just allocate Op and append to parent */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); op = acpi_ps_alloc_op(walk_state->opcode); if (!op) { status = AE_NO_MEMORY; goto close_this_op; } if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_xXXfield declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } acpi_ps_append_arg(acpi_ps_get_parent_scope (parser_state), op); if ((walk_state->descending_callback != NULL)) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = op; status = walk_state-> descending_callback(walk_state, &op); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } if (ACPI_FAILURE(status)) { goto close_this_op; } } } op->common.aml_offset = walk_state->aml_offset; if (walk_state->op_info) { ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", (u32) op->common.aml_opcode, walk_state->op_info->name, op, parser_state->aml, op->common.aml_offset)); } } /* * Start arg_count at zero because we don't know if there are * any args yet */ walk_state->arg_count = 0; /* Are there any arguments that must be processed? */ if (walk_state->arg_types) { /* Get arguments */ switch (op->common.aml_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 */ acpi_ps_get_next_simple_arg(parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), op); break; case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ status = acpi_ps_get_next_namepath(walk_state, parser_state, op, 1); if (ACPI_FAILURE(status)) { goto close_this_op; } walk_state->arg_types = 0; break; default: /* * Op is not a constant or string, append each argument * to the Op */ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && !walk_state->arg_count) { walk_state->aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state-> aml_start); status = acpi_ps_get_next_arg(walk_state, parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), &arg); if (ACPI_FAILURE(status)) { goto close_this_op; } if (arg) { arg->common.aml_offset = walk_state->aml_offset; acpi_ps_append_arg(op, arg); } INCREMENT_ARG_LIST(walk_state-> arg_types); } /* Special processing for certain opcodes */ /* TBD (remove): Temporary mechanism to disable this code if needed */ #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && ((walk_state-> parse_flags & 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.aml_opcode) { case AML_IF_OP: case AML_ELSE_OP: case AML_WHILE_OP: ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); /* Skip body of if/else/while in pass 1 */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; break; default: break; } } #endif switch (op->common.aml_opcode) { 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 = parser_state->aml; op->named.length = (u32) (parser_state->pkg_end - parser_state->aml); /* Skip body of method */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; break; case AML_BUFFER_OP: case AML_PACKAGE_OP: case AML_VAR_PACKAGE_OP: if ((op->common.parent) && (op->common.parent->common. aml_opcode == AML_NAME_OP) && (walk_state->pass_number <= 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 = aml_op_start; op->named.length = (u32) (parser_state-> pkg_end - aml_op_start); /* Skip body */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; } break; case AML_WHILE_OP: if (walk_state->control_state) { walk_state->control_state-> control.package_end = parser_state->pkg_end; } break; default: /* No action for all other opcodes */ break; } break; } } /* Check for arguments that need to be processed */ if (walk_state->arg_count) { /* * There are arguments (complex ones), push Op and * prepare for argument */ status = acpi_ps_push_scope(parser_state, op, walk_state->arg_types, walk_state->arg_count); if (ACPI_FAILURE(status)) { goto close_this_op; } op = NULL; continue; } /* * All arguments have been processed -- Op is complete, * prepare for next */ walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { if (acpi_gbl_depth) { acpi_gbl_depth--; } if (op->common.aml_opcode == 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 op_region declaration, we now * know the length. */ op->named.length = (u32) (parser_state->aml - op->named.data); } } if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_xXXfield declaration (1 for * Opcode) * * body_length is unknown until we parse the body */ op->named.length = (u32) (parser_state->aml - op->named.data); } /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { walk_state->op = op; walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } } close_this_op: /* * Finished one argument of the containing scope */ parser_state->scope->parse_scope.arg_count--; /* Finished with pre_op */ if (pre_op) { acpi_ps_free_op(pre_op); pre_op = NULL; } /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method. */ walk_state->prev_op = op; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); if (op) { walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common. aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); if (op->common.aml_opcode != AML_WHILE_OP) { status2 = acpi_ds_result_stack_pop (walk_state); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } } /* Close this iteration of the While loop */ walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; status = AE_OK; break; case AE_CTRL_TERMINATE: status = AE_OK; /* Clean up */ do { if (op) { status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); return_ACPI_STATUS(status); default: /* All other non-AE_OK status */ do { if (op) { status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); /* * TBD: Cleanup parse ops on error */ #if 0 if (op == NULL) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = op; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(parser_state)) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else { op = NULL; } } /* while parser_state->Aml */
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); }
ACPI_STATUS acpi_aml_resolve_operands ( u16 opcode, ACPI_OPERAND_OBJECT **stack_ptr, ACPI_WALK_STATE *walk_state) { ACPI_OPERAND_OBJECT *obj_desc; ACPI_STATUS status = AE_OK; u8 object_type; ACPI_HANDLE temp_handle; u32 arg_types; ACPI_OPCODE_INFO *op_info; u32 this_arg_type; ACPI_OBJECT_TYPE type_needed; op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { return (AE_AML_BAD_OPCODE); } arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { return (AE_AML_INTERNAL); } /* * Normal exit is with *Types == '\0' at end of string. * Function will return an exception from within the loop upon * finding an entry which is not, and cannot be converted * to, the required type; if stack underflows; or upon * finding a NULL stack entry (which "should never happen"). */ while (GET_CURRENT_ARG_TYPE (arg_types)) { if (!stack_ptr || !*stack_ptr) { return (AE_AML_INTERNAL); } /* Extract useful items */ obj_desc = *stack_ptr; /* Decode the descriptor type */ if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { /* Node */ object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type; } else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { /* ACPI internal object */ object_type = obj_desc->common.type; /* Check for bad ACPI_OBJECT_TYPE */ if (!acpi_aml_validate_object_type (object_type)) { return (AE_AML_OPERAND_TYPE); } if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { /* * Decode the Reference */ op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { return (AE_AML_BAD_OPCODE); } switch (obj_desc->reference.op_code) { case AML_ZERO_OP: case AML_ONE_OP: case AML_ONES_OP: case AML_DEBUG_OP: case AML_NAME_OP: case AML_INDEX_OP: case AML_ARG_OP: case AML_LOCAL_OP: break; default: return (AE_AML_OPERAND_TYPE); break; } } } else { /* Invalid descriptor */ return (AE_AML_OPERAND_TYPE); } /* * Get one argument type, point to the next */ this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); INCREMENT_ARG_LIST (arg_types); /* * Handle cases where the object does not need to be * resolved to a value */ switch (this_arg_type) { case ARGI_REFERENCE: /* Reference */ case ARGI_TARGETREF: /* Need an operand of type INTERNAL_TYPE_REFERENCE */ if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { goto next_operand; } status = acpi_aml_check_object_type (INTERNAL_TYPE_REFERENCE, object_type, obj_desc); if (ACPI_FAILURE (status)) { return (status); } if (AML_NAME_OP == obj_desc->reference.op_code) { /* * Convert an indirect name ptr to direct name ptr and put * it on the stack */ temp_handle = obj_desc->reference.object; acpi_cm_remove_reference (obj_desc); (*stack_ptr) = temp_handle; } goto next_operand; break; case ARGI_ANYTYPE: /* * We don't want to resolve Index_op reference objects during * a store because this would be an implicit De_ref_of operation. * Instead, we just want to store the reference object. * -- All others must be resolved below. */ if ((opcode == AML_STORE_OP) && ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && ((*stack_ptr)->reference.op_code == AML_INDEX_OP)) { goto next_operand; } break; } /* * Resolve this object to a value */ status = acpi_aml_resolve_to_value (stack_ptr, walk_state); if (ACPI_FAILURE (status)) { return (status); } /* * Check the resulting object (value) type */ switch (this_arg_type) { /* * For the simple cases, only one type of resolved object * is allowed */ case ARGI_NUMBER: /* Number */ /* Need an operand of type ACPI_TYPE_NUMBER */ type_needed = ACPI_TYPE_NUMBER; break; case ARGI_BUFFER: /* Need an operand of type ACPI_TYPE_BUFFER */ type_needed = ACPI_TYPE_BUFFER; break; case ARGI_MUTEX: /* Need an operand of type ACPI_TYPE_MUTEX */ type_needed = ACPI_TYPE_MUTEX; break; case ARGI_EVENT: /* Need an operand of type ACPI_TYPE_EVENT */ type_needed = ACPI_TYPE_EVENT; break; case ARGI_REGION: /* Need an operand of type ACPI_TYPE_REGION */ type_needed = ACPI_TYPE_REGION; break; case ARGI_IF: /* If */ /* Need an operand of type INTERNAL_TYPE_IF */ type_needed = INTERNAL_TYPE_IF; break; case ARGI_PACKAGE: /* Package */ /* Need an operand of type ACPI_TYPE_PACKAGE */ type_needed = ACPI_TYPE_PACKAGE; break; case ARGI_ANYTYPE: /* Any operand type will do */ type_needed = ACPI_TYPE_ANY; break; /* * The more complex cases allow multiple resolved object types */ case ARGI_STRING: /* Need an operand of type ACPI_TYPE_STRING or ACPI_TYPE_BUFFER */ if ((ACPI_TYPE_STRING != (*stack_ptr)->common.type) && (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) { return (AE_AML_OPERAND_TYPE); } goto next_operand; break; case ARGI_DATAOBJECT: /* * ARGI_DATAOBJECT is only used by the Size_of operator. * * The ACPI specification allows Size_of to return the size of * a Buffer, String or Package. However, the MS ACPI.SYS AML * Interpreter also allows an Node reference to return without * error with a size of 4. */ /* Need a buffer, string, package or Node reference */ if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) { return (AE_AML_OPERAND_TYPE); } /* * If this is a reference, only allow a reference to an Node. */ if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { if (!(*stack_ptr)->reference.node) { return (AE_AML_OPERAND_TYPE); } } goto next_operand; break; case ARGI_COMPLEXOBJ: /* Need a buffer or package */ if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) { return (AE_AML_OPERAND_TYPE); } goto next_operand; break; default: /* Unknown type */ return (AE_BAD_PARAMETER); } /* * Make sure that the original object was resolved to the * required object type (Simple cases only). */ status = acpi_aml_check_object_type (type_needed, (*stack_ptr)->common.type, *stack_ptr); if (ACPI_FAILURE (status)) { return (status); } next_operand: /* * If more operands needed, decrement Stack_ptr to point * to next operand on stack */ if (GET_CURRENT_ARG_TYPE (arg_types)) { stack_ptr--; } } /* while (*Types) */ return (status); }
static ACPI_STATUS AcpiPsGetArguments ( ACPI_WALK_STATE *WalkState, UINT8 *AmlOpStart, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status = AE_OK; ACPI_PARSE_OBJECT *Arg = NULL; const ACPI_OPCODE_INFO *OpInfo; ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Get arguments for opcode [%s]\n", Op->Common.AmlOpName)); 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 */ AcpiPsGetNextSimpleArg (&(WalkState->ParserState), GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); break; case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, ACPI_POSSIBLE_METHOD_CALL); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } WalkState->ArgTypes = 0; break; default: /* * Op is not a constant or string, append each argument to the Op */ while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) { WalkState->Aml = WalkState->ParserState.Aml; switch (Op->Common.AmlOpcode) { case AML_METHOD_OP: case AML_BUFFER_OP: case AML_PACKAGE_OP: case AML_VARIABLE_PACKAGE_OP: case AML_WHILE_OP: break; default: ASL_CV_CAPTURE_COMMENTS (WalkState); break; } Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Arg) { AcpiPsAppendArg (Op, Arg); } INCREMENT_ARG_LIST (WalkState->ArgTypes); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Final argument count: %8.8X pass %u\n", WalkState->ArgCount, WalkState->PassNumber)); /* * This case handles the legacy option that groups all module-level * code blocks together and defers execution until all of the tables * are loaded. Execute all of these blocks at this time. * Execute any module-level code that was detected during the table * load phase. * * Note: this option is deprecated and will be eliminated in the * future. Use of this option can cause problems with AML code that * depends upon in-order immediate execution of module-level code. */ if (AcpiGbl_GroupModuleLevelCode && (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) && ((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: /* * Currently supported module-level opcodes are: * IF/ELSE/WHILE. These appear to be the most common, * and easiest to support since they open an AML * package. */ if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) { AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart, (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart), WalkState->OwnerId); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); /* Skip body of if/else/while in pass 1 */ WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; WalkState->ArgCount = 0; break; default: /* * Check for an unsupported executable opcode at module * level. We must be in PASS1, the parent must be a SCOPE, * The opcode class must be EXECUTE, and the opcode must * not be an argument to another opcode. */ if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) && (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) { OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); if ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Arg)) { ACPI_WARNING ((AE_INFO, "Unsupported module-level executable opcode " "0x%.2X at table offset 0x%.4X", Op->Common.AmlOpcode, (UINT32) (ACPI_PTR_DIFF (AmlOpStart, WalkState->ParserState.AmlStart) + sizeof (ACPI_TABLE_HEADER)))); } } break; } } /* Special processing for certain opcodes */ 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 = WalkState->ParserState.Aml; Op->Named.Length = (UINT32) (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); /* Skip body of method */ WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; WalkState->ArgCount = 0; break; case AML_BUFFER_OP: case AML_PACKAGE_OP: case AML_VARIABLE_PACKAGE_OP: if ((Op->Common.Parent) && (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Setup Package/Buffer: Pass %u, AML Ptr: %p\n", WalkState->PassNumber, AmlOpStart)); /* * 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: if (WalkState->ControlState) { WalkState->ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd; } break; default: /* No action for all other opcodes */ break; } break; } return_ACPI_STATUS (AE_OK); }