static ACPI_STATUS LdCommonNamespaceEnd ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_OBJECT_TYPE ObjectType; BOOLEAN ForceNewScope = FALSE; ACPI_FUNCTION_NAME (LdCommonNamespaceEnd); /* We are only interested in opcodes that have an associated name */ if (!Op->Asl.Namepath) { return (AE_OK); } /* Get the type to determine if we should pop the scope */ if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)) { /* TBD: Merge into AcpiDsMapNamedOpcodeToDataType */ ObjectType = ACPI_TYPE_LOCAL_RESOURCE; } else { ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); } /* Pop scope that was pushed for Resource Templates */ if (Op->Asl.ParseOpcode == PARSEOP_NAME) { if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } } /* Pop the scope stack */ if (ForceNewScope || AcpiNsOpensScope (ObjectType)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op [%s] %p\n", AcpiUtGetTypeName (ObjectType), Op->Asl.ParseOpName, Op)); (void) AcpiDsScopeStackPop (WalkState); } return (AE_OK); }
static ACPI_STATUS XfNamespaceLocateEnd ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd); /* We are only interested in opcodes that have an associated name */ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); if (!(OpInfo->Flags & AML_NAMED)) { return_ACPI_STATUS (AE_OK); } /* Not interested in name references, we did not open a scope for them */ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) || (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) { return_ACPI_STATUS (AE_OK); } /* Pop the scope stack if necessary */ if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode))) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "%s: Popping scope for Op %p\n", AcpiUtGetTypeName (OpInfo->ObjectType), Op)); (void) AcpiDsScopeStackPop (WalkState); } return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiDmResourceDescendingOp ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_WALK_STATE *WalkState; ACPI_OBJECT_TYPE ObjectType; ACPI_STATUS Status; WalkState = Info->WalkState; OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); /* Open new scope if necessary */ ObjectType = OpInfo->ObjectType; if (AcpiNsOpensScope (ObjectType)) { if (Op->Common.Node) { Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } } /* * Check if this operator contains a reference to a resource descriptor. * If so, convert the reference into a symbolic reference. */ AcpiDmCheckResourceReference (Op, WalkState); return (AE_OK); }
static ACPI_STATUS AcpiDmCommonAscendingOp ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_OBJECT_TYPE ObjectType; /* Close scope if necessary */ OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); ObjectType = OpInfo->ObjectType; ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); if (AcpiNsOpensScope (ObjectType)) { (void) AcpiDsScopeStackPop (Info->WalkState); } return (AE_OK); }
static ACPI_STATUS LdNamespace2Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_OBJECT_TYPE ObjectType; BOOLEAN ForceNewScope = FALSE; ACPI_PARSE_OBJECT *Arg; char *Path; ACPI_NAMESPACE_NODE *TargetNode; ACPI_FUNCTION_NAME (LdNamespace2Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); /* Ignore Ops with no namespace node */ Node = Op->Asl.Node; if (!Node) { return (AE_OK); } /* Get the type to determine if we should push the scope */ if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)) { ObjectType = ACPI_TYPE_LOCAL_RESOURCE; } else { ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); } /* Push scope for Resource Templates */ if (Op->Asl.ParseOpcode == PARSEOP_NAME) { if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } } /* Push the scope stack */ if (ForceNewScope || AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) { /* Complete the alias node by getting and saving the target node */ /* First child is the alias target */ Arg = Op->Asl.Child; /* Get the target pathname */ Path = Arg->Asl.Namepath; if (!Path) { Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); if (ACPI_FAILURE (Status)) { return (Status); } } /* Get the NS node associated with the target. It must exist. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, &TargetNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); /* * The name was not found, go ahead and create it. * This prevents more errors later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH, WalkState, &(Node)); return (AE_OK); } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return (AE_OK); } /* Save the target node within the alias node */ Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); } return (AE_OK); }
static ACPI_STATUS LdNamespace1Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; char *Path; UINT32 Flags = ACPI_NS_NO_UPSEARCH; ACPI_PARSE_OBJECT *Arg; UINT32 i; BOOLEAN ForceNewScope = FALSE; ACPI_FUNCTION_NAME (LdNamespace1Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); /* * We are only interested in opcodes that have an associated name * (or multiple names) */ switch (Op->Asl.AmlOpcode) { case AML_BANK_FIELD_OP: case AML_INDEX_FIELD_OP: case AML_FIELD_OP: Status = LdLoadFieldElements (Op, WalkState); return (Status); default: /* All other opcodes go below */ break; } /* Check if this object has already been installed in the namespace */ if (Op->Asl.Node) { return (AE_OK); } Path = Op->Asl.Namepath; if (!Path) { return (AE_OK); } /* Map the raw opcode into an internal object type */ switch (Op->Asl.ParseOpcode) { case PARSEOP_NAME: Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ /* * If this name refers to a ResourceTemplate, we will need to open * a new scope so that the resource subfield names can be entered into * the namespace underneath this name */ if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } /* Get the data type associated with the named object, not the name itself */ /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ ObjectType = 1; for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) { ObjectType++; } break; case PARSEOP_EXTERNAL: /* * "External" simply enters a name and type into the namespace. * We must be careful to not open a new scope, however, no matter * what type the external name refers to (e.g., a method) * * first child is name, next child is ObjectType */ ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; ObjectType = ACPI_TYPE_ANY; /* * We will mark every new node along the path as "External". This * allows some or all of the nodes to be created later in the ASL * code. Handles cases like this: * * External (\_SB_.PCI0.ABCD, IntObj) * Scope (_SB_) * { * Device (PCI0) * { * } * } * Method (X) * { * Store (\_SB_.PCI0.ABCD, Local0) * } */ Flags |= ACPI_NS_EXTERNAL; break; case PARSEOP_DEFAULT_ARG: if (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC) { Status = LdLoadResourceElements (Op, WalkState); return_ACPI_STATUS (Status); } ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; case PARSEOP_SCOPE: /* * The name referenced by Scope(Name) must already exist at this point. * In other words, forward references for Scope() are not supported. * The only real reason for this is that the MS interpreter cannot * handle this case. Perhaps someday this case can go away. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* The name was not found, go ahead and create it */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &(Node)); /* * However, this is an error -- primarily because the MS * interpreter can't handle a forward reference from the * Scope() operator. */ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, Op->Asl.ExternalName); goto FinishNode; } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } /* We found a node with this name, now check the type */ switch (Node->Type) { case ACPI_TYPE_LOCAL_SCOPE: case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types - they all open a new scope */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Which is used to workaround the fact that the MS interpreter * does not allow Scope() forward references. */ sprintf (MsgBuffer, "%s [%s], changing type to [Scope]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* Switch the type to scope, open the new scope */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; default: /* All other types are an error */ sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* * However, switch the type to be an actual scope so * that compilation can continue without generating a whole * cascade of additional errors. Open the new scope. */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; } Status = AE_OK; goto FinishNode; default: ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); /* The name must not already exist */ Flags |= ACPI_NS_ERROR_IF_FOUND; /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) { /* Allow multiple references to the same scope */ Node->Type = (UINT8) ObjectType; Status = AE_OK; } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) { /* * Allow one create on an object or segment that was * previously declared External */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; } else { /* Valid error, object already exists */ AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName); return_ACPI_STATUS (AE_OK); } } else { AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } } if (ForceNewScope) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } FinishNode: /* * Point the parse node to the new namespace node, and point * the Node back to the original Parse node */ Op->Asl.Node = Node; Node->Op = Op; /* Set the actual data type if appropriate (EXTERNAL term only) */ if (ActualObjectType != ACPI_TYPE_ANY) { Node->Type = (UINT8) ActualObjectType; Node->Value = ASL_EXTERNAL_METHOD; } if (Op->Asl.ParseOpcode == PARSEOP_METHOD) { /* * Get the method argument count from "Extra" and save * it in the namespace node */ Node->Value = (UINT32) Op->Asl.Extra; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsLoad1BeginOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp) { ACPI_PARSE_OBJECT *Op; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; char *Path; UINT32 Flags; ACPI_FUNCTION_TRACE (DsLoad1BeginOp); Op = WalkState->Op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); /* We are only interested in opcodes that have an associated name */ if (Op) { if (!(WalkState->OpInfo->Flags & AML_NAMED)) { *OutOp = Op; return_ACPI_STATUS (AE_OK); } /* Check if this object has already been installed in the namespace */ if (Op->Common.Node) { *OutOp = Op; return_ACPI_STATUS (AE_OK); } } Path = AcpiPsGetNextNamestring (&WalkState->ParserState); /* Map the raw opcode into an internal object type */ ObjectType = WalkState->OpInfo->ObjectType; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "State=%p Op=%p [%s]\n", WalkState, Op, AcpiUtGetTypeName (ObjectType))); switch (WalkState->Opcode) { case AML_SCOPE_OP: /* * The target name of the Scope() operator must exist at this point so * that we can actually open the scope to enter new names underneath it. * Allow search-to-root for single namesegs. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); #ifdef ACPI_ASL_COMPILER if (Status == AE_NOT_FOUND) { /* * Table disassembly: * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0, 0); Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, WalkState, &Node); } #endif if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (Path, Status); return_ACPI_STATUS (Status); } /* * Check to make sure that the target is * one of the opcodes that actually opens a scope */ switch (Node->Type) { case ACPI_TYPE_ANY: case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Note: silently change the type here. On the second pass, * we will report a warning */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Type override - [%4.4s] had invalid type (%s) " "for Scope operator, changed to type ANY\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); Node->Type = ACPI_TYPE_ANY; WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; break; case ACPI_TYPE_METHOD: /* * Allow scope change to root during execution of module-level * code. Root is typed METHOD during this time. */ if ((Node == AcpiGbl_RootNode) && (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) { break; } /*lint -fallthrough */ default: /* All other types are an error */ ACPI_ERROR ((AE_INFO, "Invalid type (%s) for target of " "Scope operator [%4.4s] (Cannot override)", AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } break; default: /* * For all other named opcodes, we will enter the name into * the namespace. * * Setup the search flags. * Since we are entering a name into the namespace, we do not want to * enable the search-to-root upsearch. * * There are only two conditions where it is acceptable that the name * already exists: * 1) the Scope() operator can reopen a scoping object that was * previously defined (Scope, Method, Device, etc.) * 2) Whenever we are parsing a deferred opcode (OpRegion, Buffer, * BufferField, or Package), the name of the object is already * in the namespace. */ if (WalkState->DeferredNode) { /* This name is already in the namespace, get the node */ Node = WalkState->DeferredNode; Status = AE_OK; break; } /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (WalkState->MethodNode) { Node = NULL; Status = AE_OK; break; } Flags = ACPI_NS_NO_UPSEARCH; if ((WalkState->Opcode != AML_SCOPE_OP) && (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP))) { if (WalkState->NamespaceOverride) { Flags |= ACPI_NS_OVERRIDE_IF_FOUND; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n", AcpiUtGetTypeName (ObjectType))); } else { Flags |= ACPI_NS_ERROR_IF_FOUND; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", AcpiUtGetTypeName (ObjectType))); } } else { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", AcpiUtGetTypeName (ObjectType))); } /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Flags & ANOBJ_IS_EXTERNAL) { /* * Allow one create on an object or segment that was * previously declared External */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; } } if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (Path, Status); return_ACPI_STATUS (Status); } } break; } /* Common exit */ if (!Op) { /* Create a new op */ Op = AcpiPsAllocOp (WalkState->Opcode); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } } /* Initialize the op */ #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) Op->Named.Path = ACPI_CAST_PTR (UINT8, Path); #endif if (Node) { /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ Op->Common.Node = Node; Op->Named.Name = Node->Name.Integer; } AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op); *OutOp = Op; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsLookup ( ACPI_GENERIC_STATE *ScopeInfo, char *Pathname, ACPI_OBJECT_TYPE Type, ACPI_INTERPRETER_MODE InterpreterMode, UINT32 Flags, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE **ReturnNode) { ACPI_STATUS Status; char *Path = Pathname; ACPI_NAMESPACE_NODE *PrefixNode; ACPI_NAMESPACE_NODE *CurrentNode = NULL; ACPI_NAMESPACE_NODE *ThisNode = NULL; UINT32 NumSegments; UINT32 NumCarats; ACPI_NAME SimpleName; ACPI_OBJECT_TYPE TypeToCheckFor; ACPI_OBJECT_TYPE ThisSearchType; UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; UINT32 LocalFlags; ACPI_FUNCTION_TRACE (NsLookup); if (!ReturnNode) { return_ACPI_STATUS (AE_BAD_PARAMETER); } LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | ACPI_NS_SEARCH_PARENT); *ReturnNode = ACPI_ENTRY_NOT_FOUND; AcpiGbl_NsLookupCount++; if (!AcpiGbl_RootNode) { return_ACPI_STATUS (AE_NO_NAMESPACE); } /* Get the prefix scope. A null scope means use the root scope */ if ((!ScopeInfo) || (!ScopeInfo->Scope.Node)) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", AcpiGbl_RootNode)); PrefixNode = AcpiGbl_RootNode; } else { PrefixNode = ScopeInfo->Scope.Node; if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); return_ACPI_STATUS (AE_AML_INTERNAL); } if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a * Device/Method, etc.) It could be a Package or other object * node. Backup up the tree to find the containing scope node. */ while (!AcpiNsOpensScope (PrefixNode->Type) && PrefixNode->Type != ACPI_TYPE_ANY) { PrefixNode = PrefixNode->Parent; } } } /* Save type. TBD: may be no longer necessary */ TypeToCheckFor = Type; /* * Begin examination of the actual pathname */ if (!Pathname) { /* A Null NamePath is allowed and refers to the root */ NumSegments = 0; ThisNode = AcpiGbl_RootNode; Path = ""; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null Pathname (Zero segments), Flags=%X\n", Flags)); } else { /* * Name pointer is valid (and must be in internal name format) * * Check for scope prefixes: * * As represented in the AML stream, a namepath consists of an * optional scope prefix followed by a name segment part. * * If present, the scope prefix is either a Root Prefix (in * which case the name is fully qualified), or one or more * Parent Prefixes (in which case the name's scope is relative * to the current scope). */ if (*Path == (UINT8) AML_ROOT_PREFIX) { /* Pathname is fully qualified, start from the root */ ThisNode = AcpiGbl_RootNode; SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Point to name segment part */ Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Path is absolute from root [%p]\n", ThisNode)); } else { /* Pathname is relative to current scope, start there */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", AcpiUtGetNodeName (PrefixNode), PrefixNode)); /* * Handle multiple Parent Prefixes (carat) by just getting * the parent node for each prefix instance. */ ThisNode = PrefixNode; NumCarats = 0; while (*Path == (UINT8) AML_PARENT_PREFIX) { /* Name is fully qualified, no search rules apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* * Point past this prefix to the name segment * part or the next Parent Prefix */ Path++; /* Backup to the parent node */ NumCarats++; ThisNode = ThisNode->Parent; if (!ThisNode) { /* Current scope has no parent scope */ ACPI_ERROR ((AE_INFO, "%s: Path has too many parent prefixes (^) " "- reached beyond root node", Pathname)); return_ACPI_STATUS (AE_NOT_FOUND); } } if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %u carat(s)\n", AcpiUtGetNodeName (ThisNode), NumCarats)); } } /* * Determine the number of ACPI name segments in this pathname. * * The segment part consists of either: * - A Null name segment (0) * - A DualNamePrefix followed by two 4-byte name segments * - A MultiNamePrefix followed by a byte indicating the * number of segments and the segments themselves. * - A single 4-byte name segment * * Examine the name prefix opcode, if any, to determine the number of * segments. */ switch (*Path) { case 0: /* * Null name after a root or parent prefixes. We already * have the correct target node and there are no name segments. */ NumSegments = 0; Type = ThisNode->Type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Prefix-only Pathname (Zero name segments), Flags=%X\n", Flags)); break; case AML_DUAL_NAME_PREFIX: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Two segments, point to first name segment */ NumSegments = 2; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Dual Pathname (2 segments, Flags=%X)\n", Flags)); break; case AML_MULTI_NAME_PREFIX_OP: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Extract segment count, point to first name segment */ Path++; NumSegments = (UINT32) (UINT8) *Path; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Multi Pathname (%u Segments, Flags=%X)\n", NumSegments, Flags)); break; default: /* * Not a Null name, no Dual or Multi prefix, hence there is * only one name segment and Pathname is already pointing to it. */ NumSegments = 1; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Simple Pathname (1 segment, Flags=%X)\n", Flags)); break; } ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); } /* * Search namespace for each segment of the name. Loop through and * verify (or add to the namespace) each name segment. * * The object type is significant only at the last name * segment. (We don't care about the types along the path, only * the type of the final target object.) */ ThisSearchType = ACPI_TYPE_ANY; CurrentNode = ThisNode; while (NumSegments && CurrentNode) { NumSegments--; if (!NumSegments) { /* This is the last segment, enable typechecking */ ThisSearchType = Type; /* * Only allow automatic parent search (search rules) if the caller * requested it AND we have a single, non-fully-qualified NameSeg */ if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && (Flags & ACPI_NS_SEARCH_PARENT)) { LocalFlags |= ACPI_NS_SEARCH_PARENT; } /* Set error flag according to caller */ if (Flags & ACPI_NS_ERROR_IF_FOUND) { LocalFlags |= ACPI_NS_ERROR_IF_FOUND; } /* Set override flag according to caller */ if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) { LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND; } } /* Extract one ACPI name from the front of the pathname */ ACPI_MOVE_32_TO_32 (&SimpleName, Path); /* Try to find the single (4 character) ACPI name */ Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, InterpreterMode, ThisSearchType, LocalFlags, &ThisNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name [%4.4s] not found in scope [%4.4s] %p\n", (char *) &SimpleName, (char *) &CurrentNode->Name, CurrentNode)); } *ReturnNode = ThisNode; return_ACPI_STATUS (Status); } /* More segments to follow? */ if (NumSegments > 0) { /* * If we have an alias to an object that opens a scope (such as a * device or processor), we need to dereference the alias here so * that we can access any children of the original node (via the * remaining segments). */ if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) { if (!ThisNode->Object) { return_ACPI_STATUS (AE_NOT_EXIST); } if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) ThisNode->Object)->Type)) { ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; } } } /* Special handling for the last segment (NumSegments == 0) */ else { /* * Sanity typecheck of the target object: * * If 1) This is the last segment (NumSegments == 0) * 2) And we are looking for a specific type * (Not checking for TYPE_ANY) * 3) Which is not an alias * 4) Which is not a local type (TYPE_SCOPE) * 5) And the type of target object is known (not TYPE_ANY) * 6) And target object does not match what we are looking for * * Then we have a type mismatch. Just warn and ignore it. */ if ((TypeToCheckFor != ACPI_TYPE_ANY) && (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && (ThisNode->Type != ACPI_TYPE_ANY) && (ThisNode->Type != TypeToCheckFor)) { /* Complain about a type mismatch */ ACPI_WARNING ((AE_INFO, "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR (char, &SimpleName), AcpiUtGetTypeName (ThisNode->Type), AcpiUtGetTypeName (TypeToCheckFor))); } /* * If this is the last name segment and we are not looking for a * specific type, but the type of found object is known, use that * type to (later) see if it opens a scope. */ if (Type == ACPI_TYPE_ANY) { Type = ThisNode->Type; } } /* Point to next name segment and make this node current */ Path += ACPI_NAME_SIZE; CurrentNode = ThisNode; }
ACPI_STATUS AcpiDsExecBeginOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp) { ACPI_PARSE_OBJECT *Op; ACPI_STATUS Status = AE_OK; UINT32 OpcodeClass; ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState); Op = WalkState->Op; if (!Op) { Status = AcpiDsLoad2BeginOp (WalkState, OutOp); if (ACPI_FAILURE (Status)) { goto ErrorExit; } Op = *OutOp; WalkState->Op = Op; WalkState->Opcode = Op->Common.AmlOpcode; WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n", AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op)); Status = AcpiDsScopeStackPop (WalkState); if (ACPI_FAILURE (Status)) { goto ErrorExit; } } } if (Op == WalkState->Origin) { if (OutOp) { *OutOp = Op; } return_ACPI_STATUS (AE_OK); } /* * If the previous opcode was a conditional, this opcode * must be the beginning of the associated predicate. * Save this knowledge in the current scope descriptor */ if ((WalkState->ControlState) && (WalkState->ControlState->Common.State == ACPI_CONTROL_CONDITIONAL_EXECUTING)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n", Op, WalkState)); WalkState->ControlState->Common.State = ACPI_CONTROL_PREDICATE_EXECUTING; /* Save start of predicate */ WalkState->ControlState->Control.PredicateOp = Op; } OpcodeClass = WalkState->OpInfo->Class; /* We want to send namepaths to the load code */ if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { OpcodeClass = AML_CLASS_NAMED_OBJECT; } /* * Handle the opcode based upon the opcode type */ switch (OpcodeClass) { case AML_CLASS_CONTROL: Status = AcpiDsExecBeginControlOp (WalkState, Op); break; case AML_CLASS_NAMED_OBJECT: if (WalkState->WalkType & ACPI_WALK_METHOD) { /* * Found a named object declaration during method execution; * we must enter this object into the namespace. The created * object is temporary and will be deleted upon completion of * the execution of this method. * * Note 10/2010: Except for the Scope() op. This opcode does * not actually create a new object, it refers to an existing * object. However, for Scope(), we want to indeed open a * new scope. */ if (Op->Common.AmlOpcode != AML_SCOPE_OP) { Status = AcpiDsLoad2BeginOp (WalkState, NULL); } else { Status = AcpiDsScopeStackPush ( Op->Named.Node, Op->Named.Node->Type, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } } break; case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: break; default: break; } /* Nothing to do here during method execution */ return_ACPI_STATUS (Status); ErrorExit: Status = AcpiDsMethodError (Status, WalkState); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiDmXrefDescendingOp ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_WALK_STATE *WalkState; ACPI_OBJECT_TYPE ObjectType; ACPI_OBJECT_TYPE ObjectType2; ACPI_STATUS Status; char *Path = NULL; ACPI_PARSE_OBJECT *NextOp; ACPI_NAMESPACE_NODE *Node; ACPI_OPERAND_OBJECT *Object; WalkState = Info->WalkState; OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); ObjectType = OpInfo->ObjectType; ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); if ((!(OpInfo->Flags & AML_NAMED)) && (!(OpInfo->Flags & AML_CREATE)) && (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) { goto Exit; } /* Get the NamePath from the appropriate place */ if (OpInfo->Flags & AML_NAMED) { if ((Op->Common.AmlOpcode == AML_ALIAS_OP) || (Op->Common.AmlOpcode == AML_SCOPE_OP)) { /* * Only these two operators refer to an existing name, * first argument */ Path = (char *) Op->Named.Path; } } else if (OpInfo->Flags & AML_CREATE) { /* Referenced Buffer Name is the first child */ NextOp = Op->Common.Value.Arg; if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { Path = NextOp->Common.Value.String; } } else { Path = Op->Common.Value.String; } if (!Path) { goto Exit; } /* * Lookup the name in the namespace. Name must exist at this point, or it * is an invalid reference. * * The namespace is also used as a lookup table for references to resource * descriptors and the fields within them. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { AcpiDmAddToExternalList (Path, (UINT8) ObjectType, 0); /* * We could install this into the namespace, but we catch duplicate * externals when they are added to the list. */ #if 0 Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE, WalkState, &Node); #endif } } /* * Found the node in external table, add it to external list * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc */ else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId) { ObjectType2 = ObjectType; Object = AcpiNsGetAttachedObject (Node); if (Object) { ObjectType2 = Object->Common.Type; } if (ObjectType2 == ACPI_TYPE_METHOD) { AcpiDmAddToExternalList (Path, ACPI_TYPE_METHOD, Object->Method.ParamCount); } else { AcpiDmAddToExternalList (Path, (UINT8) ObjectType2, 0); } Op->Common.Node = Node; } else { Op->Common.Node = Node; } Exit: /* Open new scope if necessary */ if (AcpiNsOpensScope (ObjectType)) { if (Op->Common.Node) { Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } } return (AE_OK); }
static ACPI_STATUS AcpiDmLoadDescendingOp ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_WALK_STATE *WalkState; ACPI_OBJECT_TYPE ObjectType; ACPI_STATUS Status; char *Path = NULL; ACPI_PARSE_OBJECT *NextOp; ACPI_NAMESPACE_NODE *Node; char FieldPath[5]; BOOLEAN PreDefined = FALSE; UINT8 PreDefineIndex = 0; WalkState = Info->WalkState; OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); ObjectType = OpInfo->ObjectType; ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); /* Only interested in operators that create new names */ if (!(OpInfo->Flags & AML_NAMED) && !(OpInfo->Flags & AML_CREATE)) { goto Exit; } /* Get the NamePath from the appropriate place */ if (OpInfo->Flags & AML_NAMED) { /* For all named operators, get the new name */ Path = (char *) Op->Named.Path; if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) { *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; FieldPath[4] = 0; Path = FieldPath; } } else if (OpInfo->Flags & AML_CREATE) { /* New name is the last child */ NextOp = Op->Common.Value.Arg; while (NextOp->Common.Next) { NextOp = NextOp->Common.Next; } Path = NextOp->Common.Value.String; } if (!Path) { goto Exit; } /* Insert the name into the namespace */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, WalkState, &Node); Op->Common.Node = Node; if (ACPI_SUCCESS (Status)) { /* Check if it's a predefined node */ while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) { if (!ACPI_STRNCMP (Node->Name.Ascii, AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4)) { PreDefined = TRUE; break; } PreDefineIndex++; } /* * Set node owner id if it satisfies all the following conditions: * 1) Not a predefined node, _SB_ etc * 2) Not the root node * 3) Not a node created by Scope */ if (!PreDefined && Node != AcpiGbl_RootNode && Op->Common.AmlOpcode != AML_SCOPE_OP) { Node->OwnerId = WalkState->OwnerId; } } Exit: if (AcpiNsOpensScope (ObjectType)) { if (Op->Common.Node) { Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } } return (AE_OK); }
static ACPI_STATUS LdNamespace1Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *MethodOp; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; char *Path; UINT32 Flags = ACPI_NS_NO_UPSEARCH; ACPI_PARSE_OBJECT *Arg; UINT32 i; BOOLEAN ForceNewScope = FALSE; const ACPI_OPCODE_INFO *OpInfo; ACPI_PARSE_OBJECT *ParentOp; ACPI_FUNCTION_NAME (LdNamespace1Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); /* * We are only interested in opcodes that have an associated name * (or multiple names) */ switch (Op->Asl.AmlOpcode) { case AML_BANK_FIELD_OP: case AML_INDEX_FIELD_OP: case AML_FIELD_OP: Status = LdLoadFieldElements (Op, WalkState); return (Status); case AML_INT_CONNECTION_OP: if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) { break; } Arg = Op->Asl.Child; Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &Node); if (ACPI_FAILURE (Status)) { break; } if (Node->Type == ACPI_TYPE_BUFFER) { Arg->Asl.Node = Node; Arg = Node->Op->Asl.Child; /* Get namepath */ Arg = Arg->Asl.Next; /* Get actual buffer */ Arg = Arg->Asl.Child; /* Buffer length */ Arg = Arg->Asl.Next; /* RAW_DATA buffer */ } break; default: /* All other opcodes go below */ break; } /* Check if this object has already been installed in the namespace */ if (Op->Asl.Node) { return (AE_OK); } /* Check for a possible illegal forward reference */ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)) { /* * Op->Asl.Namepath will be NULL for these opcodes. * These opcodes are guaranteed to have a parent. * Examine the parent opcode. */ Status = AE_OK; ParentOp = Op->Asl.Parent; OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Asl.AmlOpcode); /* * Exclude all operators that actually declare a new name: * Name (ABCD, 1) -> Ignore (AML_CLASS_NAMED_OBJECT) * We only want references to named objects: * Store (2, WXYZ) -> Attempt to resolve the name */ if (OpInfo->Class == AML_CLASS_NAMED_OBJECT) { return (AE_OK); } /* * Check if the referenced object exists at this point during * the load: * 1) If it exists, then this cannot be a forward reference. * 2) If it does not exist, it could be a forward reference or * it truly does not exist (and no external declaration). */ Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Asl.Value.Name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, &Node); if (Status == AE_NOT_FOUND) { /* * This is either a foward reference or the object truly * does not exist. The two cases can only be differentiated * during the cross-reference stage later. Mark the Op/Name * as not-found for now to indicate the need for further * processing. * * Special case: Allow forward references from elements of * Package objects. This provides compatibility with other * ACPI implementations. To correctly implement this, the * ACPICA table load defers package resolution until the entire * namespace has been loaded. */ if ((ParentOp->Asl.ParseOpcode != PARSEOP_PACKAGE) && (ParentOp->Asl.ParseOpcode != PARSEOP_VAR_PACKAGE)) { Op->Asl.CompileFlags |= OP_NOT_FOUND_DURING_LOAD; } return (AE_OK); } return (Status); } Path = Op->Asl.Namepath; if (!Path) { return (AE_OK); } /* Map the raw opcode into an internal object type */ switch (Op->Asl.ParseOpcode) { case PARSEOP_NAME: Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ /* * If this name refers to a ResourceTemplate, we will need to open * a new scope so that the resource subfield names can be entered into * the namespace underneath this name */ if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } /* Get the data type associated with the named object, not the name itself */ /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ ObjectType = 1; for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) { ObjectType++; } break; case PARSEOP_EXTERNAL: /* * "External" simply enters a name and type into the namespace. * We must be careful to not open a new scope, however, no matter * what type the external name refers to (e.g., a method) * * first child is name, next child is ObjectType */ ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; ObjectType = ACPI_TYPE_ANY; /* * We will mark every new node along the path as "External". This * allows some or all of the nodes to be created later in the ASL * code. Handles cases like this: * * External (\_SB_.PCI0.ABCD, IntObj) * Scope (_SB_) * { * Device (PCI0) * { * } * } * Method (X) * { * Store (\_SB_.PCI0.ABCD, Local0) * } */ Flags |= ACPI_NS_EXTERNAL; break; case PARSEOP_DEFAULT_ARG: if (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC) { Status = LdLoadResourceElements (Op, WalkState); return_ACPI_STATUS (Status); } ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; case PARSEOP_SCOPE: /* * The name referenced by Scope(Name) must already exist at this point. * In other words, forward references for Scope() are not supported. * The only real reason for this is that the MS interpreter cannot * handle this case. Perhaps someday this case can go away. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* The name was not found, go ahead and create it */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * However, this is an error -- primarily because the MS * interpreter can't handle a forward reference from the * Scope() operator. */ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, Op->Asl.ExternalName); goto FinishNode; } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } else /* Status AE_OK */ { /* * Do not allow references to external scopes from the DSDT. * This is because the DSDT is always loaded first, and the * external reference cannot be resolved -- causing a runtime * error because Scope() must be resolved immediately. * 10/2015. */ if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (ACPI_COMPARE_NAME (Gbl_TableSignature, "DSDT"))) { /* However, allowed if the reference is within a method */ MethodOp = Op->Asl.Parent; while (MethodOp && (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD)) { MethodOp = MethodOp->Asl.Parent; } if (!MethodOp) { /* Not in a control method, error */ AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL); } } } /* We found a node with this name, now check the type */ switch (Node->Type) { case ACPI_TYPE_LOCAL_SCOPE: case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types - they all open a new scope */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Which is used to workaround the fact that the MS interpreter * does not allow Scope() forward references. */ sprintf (MsgBuffer, "%s [%s], changing type to [Scope]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* Switch the type to scope, open the new scope */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; default: /* All other types are an error */ sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* * However, switch the type to be an actual scope so * that compilation can continue without generating a whole * cascade of additional errors. Open the new scope. */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; } Status = AE_OK; goto FinishNode; default: ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); /* The name must not already exist */ Flags |= ACPI_NS_ERROR_IF_FOUND; /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) { /* Allow multiple references to the same scope */ Node->Type = (UINT8) ObjectType; Status = AE_OK; } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) { /* * Allow one create on an object or segment that was * previously declared External */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; } else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) { /* * Allow externals in same scope as the definition of the * actual object. Similar to C. Allows multiple definition * blocks that refer to each other in the same file. */ Status = AE_OK; } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) && (ObjectType == ACPI_TYPE_ANY)) { /* Allow update of externals of unknown type. */ if (AcpiNsOpensScope (ActualObjectType)) { Node->Type = (UINT8) ActualObjectType; Status = AE_OK; } else { sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); return_ACPI_STATUS (AE_OK); } } else { /* Valid error, object already exists */ AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, Node->Op->Asl.ExternalName); return_ACPI_STATUS (AE_OK); } } else { AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } } if (ForceNewScope) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } FinishNode: /* * Point the parse node to the new namespace node, and point * the Node back to the original Parse node */ Op->Asl.Node = Node; Node->Op = Op; /* Set the actual data type if appropriate (EXTERNAL term only) */ if (ActualObjectType != ACPI_TYPE_ANY) { Node->Type = (UINT8) ActualObjectType; Node->Value = ASL_EXTERNAL_METHOD; } if (Op->Asl.ParseOpcode == PARSEOP_METHOD) { /* * Get the method argument count from "Extra" and save * it in the namespace node */ Node->Value = (UINT32) Op->Asl.Extra; } return_ACPI_STATUS (Status); }
static ACPI_STATUS LdNamespace1Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *MethodOp; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; char *Path; UINT32 Flags = ACPI_NS_NO_UPSEARCH; ACPI_PARSE_OBJECT *Arg; UINT32 i; BOOLEAN ForceNewScope = FALSE; ACPI_OWNER_ID OwnerId = 0; ACPI_FUNCTION_NAME (LdNamespace1Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); if (Op->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK) { /* * Allocate an OwnerId for this block. This helps identify the owners * of each namespace node. This is used in determining whether if * certain external declarations cause redefinition errors. */ Status = AcpiUtAllocateOwnerId (&OwnerId); WalkState->OwnerId = OwnerId; if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Failure to allocate owner ID to this definition block.", FALSE); return_ACPI_STATUS (Status); } } /* * We are only interested in opcodes that have an associated name * (or multiple names) */ switch (Op->Asl.AmlOpcode) { case AML_BANK_FIELD_OP: case AML_INDEX_FIELD_OP: case AML_FIELD_OP: Status = LdLoadFieldElements (Op, WalkState); return (Status); case AML_INT_CONNECTION_OP: if (Op->Asl.Child->Asl.AmlOpcode != AML_INT_NAMEPATH_OP) { break; } Arg = Op->Asl.Child; Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Asl.ExternalName, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &Node); if (ACPI_FAILURE (Status)) { break; } if (Node->Type == ACPI_TYPE_BUFFER) { Arg->Asl.Node = Node; Arg = Node->Op->Asl.Child; /* Get namepath */ Arg = Arg->Asl.Next; /* Get actual buffer */ Arg = Arg->Asl.Child; /* Buffer length */ Arg = Arg->Asl.Next; /* RAW_DATA buffer */ } break; default: /* All other opcodes go below */ break; } /* Check if this object has already been installed in the namespace */ if (Op->Asl.Node) { return (AE_OK); } Path = Op->Asl.Namepath; if (!Path) { return (AE_OK); } /* Map the raw opcode into an internal object type */ switch (Op->Asl.ParseOpcode) { case PARSEOP_NAME: Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ /* * If this name refers to a ResourceTemplate, we will need to open * a new scope so that the resource subfield names can be entered into * the namespace underneath this name */ if (Op->Asl.CompileFlags & OP_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } /* Get the data type associated with the named object, not the name itself */ /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ ObjectType = 1; for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) { ObjectType++; } break; case PARSEOP_EXTERNAL: /* * "External" simply enters a name and type into the namespace. * We must be careful to not open a new scope, however, no matter * what type the external name refers to (e.g., a method) * * first child is name, next child is ObjectType */ ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; ObjectType = ACPI_TYPE_ANY; /* * We will mark every new node along the path as "External". This * allows some or all of the nodes to be created later in the ASL * code. Handles cases like this: * * External (\_SB_.PCI0.ABCD, IntObj) * Scope (_SB_) * { * Device (PCI0) * { * } * } * Method (X) * { * Store (\_SB_.PCI0.ABCD, Local0) * } */ Flags |= ACPI_NS_EXTERNAL; break; case PARSEOP_DEFAULT_ARG: if (Op->Asl.CompileFlags == OP_IS_RESOURCE_DESC) { Status = LdLoadResourceElements (Op, WalkState); return_ACPI_STATUS (Status); } ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; case PARSEOP_SCOPE: /* * The name referenced by Scope(Name) must already exist at this point. * In other words, forward references for Scope() are not supported. * The only real reason for this is that the MS interpreter cannot * handle this case. Perhaps someday this case can go away. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* The name was not found, go ahead and create it */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * However, this is an error -- primarily because the MS * interpreter can't handle a forward reference from the * Scope() operator. */ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, Op->Asl.ExternalName); goto FinishNode; } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } else /* Status AE_OK */ { /* * Do not allow references to external scopes from the DSDT. * This is because the DSDT is always loaded first, and the * external reference cannot be resolved -- causing a runtime * error because Scope() must be resolved immediately. * 10/2015. */ if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (ACPI_COMPARE_NAME (Gbl_TableSignature, "DSDT"))) { /* However, allowed if the reference is within a method */ MethodOp = Op->Asl.Parent; while (MethodOp && (MethodOp->Asl.ParseOpcode != PARSEOP_METHOD)) { MethodOp = MethodOp->Asl.Parent; } if (!MethodOp) { /* Not in a control method, error */ AslError (ASL_ERROR, ASL_MSG_CROSS_TABLE_SCOPE, Op, NULL); } } } /* We found a node with this name, now check the type */ switch (Node->Type) { case ACPI_TYPE_LOCAL_SCOPE: case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types - they all open a new scope */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Which is used to workaround the fact that the MS interpreter * does not allow Scope() forward references. */ sprintf (MsgBuffer, "%s [%s], changing type to [Scope]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* Switch the type to scope, open the new scope */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; default: /* All other types are an error */ sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* * However, switch the type to be an actual scope so * that compilation can continue without generating a whole * cascade of additional errors. Open the new scope. */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; } Status = AE_OK; goto FinishNode; default: ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); /* The name must not already exist */ Flags |= ACPI_NS_ERROR_IF_FOUND; /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) { /* Allow multiple references to the same scope */ Node->Type = (UINT8) ObjectType; Status = AE_OK; } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) { /* * Allow one create on an object or segment that was * previously declared External only if WalkState->OwnerId and * Node->OwnerId are different (meaning that the current WalkState * and the Node are in different tables). */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; if (Node->OwnerId == WalkState->OwnerId && !(Node->Flags & IMPLICIT_EXTERNAL)) { AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, Node->Op->Asl.ExternalName); } if (Node->Flags & IMPLICIT_EXTERNAL) { Node->Flags &= ~IMPLICIT_EXTERNAL; } } else if (!(Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)) { /* * Allow externals in same scope as the definition of the * actual object. Similar to C. Allows multiple definition * blocks that refer to each other in the same file. However, * do not allow name declaration and an external declaration * within the same table. This is considered a re-declaration. */ Status = AE_OK; if (Node->OwnerId == WalkState->OwnerId) { AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, Node->Op->Asl.ExternalName); } } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) && (ObjectType == ACPI_TYPE_ANY)) { /* * Allow update of externals of unknown type. * In the case that multiple definition blocks are being * parsed, updating the OwnerId allows enables subsequent calls * of this method to understand which table the most recent * external declaration was seen. Without this OwnerId update, * code like the following is allowed to compile: * * DefinitionBlock("externtest.aml", "DSDT", 0x02, "Intel", "Many", 0x00000001) * { * External(ERRS,methodobj) * Method (MAIN) * { * Name(NUM2, 0) * ERRS(1,2,3) * } * } * * DefinitionBlock("externtest.aml", "SSDT", 0x02, "Intel", "Many", 0x00000001) * { * if (0) * { * External(ERRS,methodobj) * } * Method (ERRS,3) * {} * * } */ Node->OwnerId = WalkState->OwnerId; if (AcpiNsOpensScope (ActualObjectType)) { Node->Type = (UINT8) ActualObjectType; Status = AE_OK; } else { sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); return_ACPI_STATUS (AE_OK); } } else { /* Valid error, object already exists */ AslDualParseOpError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName, ASL_MSG_FOUND_HERE, Node->Op, Node->Op->Asl.ExternalName); return_ACPI_STATUS (AE_OK); } } else { AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } } if (ForceNewScope) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } FinishNode: /* * Point the parse node to the new namespace node, and point * the Node back to the original Parse node */ Op->Asl.Node = Node; Node->Op = Op; /* Set the actual data type if appropriate (EXTERNAL term only) */ if (ActualObjectType != ACPI_TYPE_ANY) { Node->Type = (UINT8) ActualObjectType; Node->Value = ASL_EXTERNAL_METHOD; } if (Op->Asl.ParseOpcode == PARSEOP_METHOD) { /* * Get the method argument count from "Extra" and save * it in the namespace node */ Node->Value = (UINT32) Op->Asl.Extra; } return_ACPI_STATUS (Status); }
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)) { ASL_CV_CAPTURE_COMMENTS (WalkState); AmlOpStart = ParserState->Aml; if (!Op) { Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); if (ACPI_FAILURE (Status)) { /* * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by * executing it as a control method. However, if we encounter * an error while loading the table, we need to keep trying to * load the table rather than aborting the table load. Set the * status to AE_OK to proceed with the table load. */ if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && Status == AE_ALREADY_EXISTS) { Status = AE_OK; } if (Status == AE_CTRL_PARSE_CONTINUE) { continue; } if (Status == AE_CTRL_PARSE_PENDING) { Status = AE_OK; } if (Status == AE_CTRL_TERMINATE) { return_ACPI_STATUS (Status); } Status = AcpiPsCompleteOp (WalkState, &Op, Status); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (AcpiNsOpensScope ( AcpiPsGetOpcodeInfo (WalkState->Opcode)->ObjectType)) { /* * If the scope/device op fails to parse, skip the body of * the scope op because the parse failure indicates that * the device may not exist. */ ACPI_ERROR ((AE_INFO, "Skip parsing opcode %s", AcpiPsGetOpcodeName (WalkState->Opcode))); WalkState->ParserState.Aml = WalkState->Aml + 1; WalkState->ParserState.Aml = AcpiPsGetNextPackageEnd(&WalkState->ParserState); WalkState->Aml = WalkState->ParserState.Aml; } continue; } AcpiExStartTraceOpcode (Op, WalkState); } /* * Start ArgCount at zero because we don't know if there are * any args yet */ WalkState->ArgCount = 0; switch (Op->Common.AmlOpcode) { case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: case AML_QWORD_OP: break; default: ASL_CV_CAPTURE_COMMENTS (WalkState); break; } /* 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); } if ((WalkState->ControlState) && ((WalkState->ControlState->Control.Opcode == AML_IF_OP) || (WalkState->ControlState->Control.Opcode == AML_WHILE_OP))) { /* * If the if/while op fails to parse, we will skip parsing * the body of the op. */ ParserState->Aml = WalkState->ControlState->Control.AmlPredicateStart + 1; ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); WalkState->Aml = ParserState->Aml; ACPI_ERROR ((AE_INFO, "Skipping While/If block")); if (*WalkState->Aml == AML_ELSE_OP) { ACPI_ERROR ((AE_INFO, "Skipping Else block")); WalkState->ParserState.Aml = WalkState->Aml + 1; WalkState->ParserState.Aml = AcpiPsGetNextPackageEnd (ParserState); WalkState->Aml = ParserState->Aml; } ACPI_FREE(AcpiUtPopGenericState (&WalkState->ControlState)); } Op = NULL; continue; } } /* Check for arguments that need to be processed */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Parseloop: argument count: %8.8X\n", WalkState->ArgCount)); 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 (Op->Common.AmlOpcode == AML_REGION_OP || Op->Common.AmlOpcode == AML_DATA_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); } if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) { /* * Backup to beginning of BankField declaration * * 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; } else if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && (ACPI_AML_EXCEPTION(Status) || Status == AE_ALREADY_EXISTS || Status == AE_NOT_FOUND)) { /* * ACPI_PARSE_MODULE_LEVEL flag means that we are currently * loading a table by executing it as a control method. * However, if we encounter an error while loading the table, * we need to keep trying to load the table rather than * aborting the table load (setting the status to AE_OK * continues the table load). If we get a failure at this * point, it means that the dispatcher got an error while * trying to execute the Op. */ 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); }