void AcpiUtNamespaceError ( const char *ModuleName, UINT32 LineNumber, const char *InternalName, ACPI_STATUS LookupStatus) { ACPI_STATUS Status; UINT32 BadName; char *Name = NULL; ACPI_MSG_REDIRECT_BEGIN; AcpiOsPrintf (ACPI_MSG_ERROR); if (LookupStatus == AE_BAD_CHARACTER) { /* There is a non-ascii character in the name */ ACPI_MOVE_32_TO_32 (&BadName, ACPI_CAST_PTR (UINT32, InternalName)); AcpiOsPrintf ("[0x%.8X] (NON-ASCII)", BadName); } else { /* Convert path to external format */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalName, NULL, &Name); /* Print target name */ if (ACPI_SUCCESS (Status)) { AcpiOsPrintf ("[%s]", Name); } else { AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]"); } if (Name) { ACPI_FREE (Name); } } AcpiOsPrintf (" Namespace lookup failure, %s", AcpiFormatException (LookupStatus)); ACPI_MSG_SUFFIX; ACPI_MSG_REDIRECT_END; }
void AcpiNsReportError ( char *ModuleName, UINT32 LineNumber, char *InternalName, ACPI_STATUS LookupStatus) { ACPI_STATUS Status; UINT32 BadName; char *Name = NULL; AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber); if (LookupStatus == AE_BAD_CHARACTER) { /* There is a non-ascii character in the name */ ACPI_MOVE_32_TO_32 (&BadName, InternalName); AcpiOsPrintf ("[0x%4.4X] (NON-ASCII)", BadName); } else { /* Convert path to external format */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalName, NULL, &Name); /* Print target name */ if (ACPI_SUCCESS (Status)) { AcpiOsPrintf ("[%s]", Name); } else { AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]"); } if (Name) { ACPI_FREE (Name); } } AcpiOsPrintf (" Namespace lookup failure, %s\n", AcpiFormatException (LookupStatus)); }
static void AcpiDmAddToExternalListFromFile ( char *Path, UINT8 Type, UINT32 Value) { char *InternalPath; char *ExternalPath; ACPI_EXTERNAL_LIST *NewExternal; ACPI_EXTERNAL_LIST *NextExternal; ACPI_EXTERNAL_LIST *PrevExternal = NULL; ACPI_STATUS Status; BOOLEAN Resolved = FALSE; if (!Path) { return; } /* TBD: Add a flags parameter */ if (Type == ACPI_TYPE_METHOD) { if (Value & 0x80) { Resolved = TRUE; } Value &= 0x07; } /* * We don't want External() statements to contain a leading '\'. * This prevents duplicate external statements of the form: * * External (\ABCD) * External (ABCD) * * This would cause a compile time error when the disassembled * output file is recompiled. */ if ((*Path == AML_ROOT_PREFIX) && (Path[1])) { Path++; } /* Check all existing externals to ensure no duplicates */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (!ACPI_STRCMP (Path, NextExternal->Path)) { /* Duplicate method, check that the Value (ArgCount) is the same */ if ((NextExternal->Type == ACPI_TYPE_METHOD) && (NextExternal->Value != Value)) { ACPI_ERROR ((AE_INFO, "(File) External method arg count mismatch %s: Current %u, override to %u", NextExternal->Path, NextExternal->Value, Value)); /* Override, since new value came from external reference file */ NextExternal->Value = Value; } /* Allow upgrade of type from ANY */ else if (NextExternal->Type == ACPI_TYPE_ANY) { NextExternal->Type = Type; NextExternal->Value = Value; } return; } NextExternal = NextExternal->Next; } /* Get the internal pathname (AML format) */ Status = AcpiNsInternalizeName (Path, &InternalPath); if (ACPI_FAILURE (Status)) { return; } /* Allocate and init a new External() descriptor */ NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); if (!NewExternal) { ACPI_FREE (InternalPath); return; } /* Must copy and normalize the input path */ AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, NULL, &ExternalPath); NewExternal->Path = ExternalPath; NewExternal->Type = Type; NewExternal->Value = Value; NewExternal->Resolved = Resolved; NewExternal->Length = (UINT16) ACPI_STRLEN (Path); NewExternal->InternalPath = InternalPath; /* Set flag to indicate External->InternalPath needs to be freed */ NewExternal->Flags |= ACPI_IPATH_ALLOCATED | ACPI_FROM_REFERENCE_FILE; /* Link the new descriptor into the global list, alphabetically ordered */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) { if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } NewExternal->Next = NextExternal; return; } PrevExternal = NextExternal; NextExternal = NextExternal->Next; } if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } }
void AcpiDmAddToExternalList ( ACPI_PARSE_OBJECT *Op, char *Path, UINT8 Type, UINT32 Value) { char *ExternalPath; char *Fullpath = NULL; ACPI_EXTERNAL_LIST *NewExternal; ACPI_EXTERNAL_LIST *NextExternal; ACPI_EXTERNAL_LIST *PrevExternal = NULL; ACPI_STATUS Status; BOOLEAN Resolved = FALSE; if (!Path) { return; } if (Type == ACPI_TYPE_METHOD) { if (Value & 0x80) { Resolved = TRUE; } Value &= 0x07; } /* * We don't want External() statements to contain a leading '\'. * This prevents duplicate external statements of the form: * * External (\ABCD) * External (ABCD) * * This would cause a compile time error when the disassembled * output file is recompiled. */ if ((*Path == AML_ROOT_PREFIX) && (Path[1])) { Path++; } /* Externalize the ACPI pathname */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, NULL, &ExternalPath); if (ACPI_FAILURE (Status)) { return; } /* * Get the full pathname from the root if "Path" has one or more * parent prefixes (^). Note: path will not contain a leading '\'. */ if (*Path == (UINT8) AML_PARENT_PREFIX) { Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); if (Fullpath) { /* Set new external path */ ACPI_FREE (ExternalPath); ExternalPath = Fullpath; } } /* Check all existing externals to ensure no duplicates */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) { /* Duplicate method, check that the Value (ArgCount) is the same */ if ((NextExternal->Type == ACPI_TYPE_METHOD) && (NextExternal->Value != Value)) { ACPI_ERROR ((AE_INFO, "External method arg count mismatch %s: Current %u, attempted %u", NextExternal->Path, NextExternal->Value, Value)); } /* Allow upgrade of type from ANY */ else if (NextExternal->Type == ACPI_TYPE_ANY) { NextExternal->Type = Type; NextExternal->Value = Value; } ACPI_FREE (ExternalPath); return; } NextExternal = NextExternal->Next; } /* Allocate and init a new External() descriptor */ NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); if (!NewExternal) { ACPI_FREE (ExternalPath); return; } NewExternal->Path = ExternalPath; NewExternal->Type = Type; NewExternal->Value = Value; NewExternal->Resolved = Resolved; NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); /* Was the external path with parent prefix normalized to a fullpath? */ if (Fullpath == ExternalPath) { /* Get new internal path */ Status = AcpiNsInternalizeName (ExternalPath, &Path); if (ACPI_FAILURE (Status)) { ACPI_FREE (ExternalPath); ACPI_FREE (NewExternal); return; } /* Set flag to indicate External->InternalPath need to be freed */ NewExternal->Flags |= ACPI_IPATH_ALLOCATED; } NewExternal->InternalPath = Path; /* Link the new descriptor into the global list, alphabetically ordered */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) { if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } NewExternal->Next = NextExternal; return; } PrevExternal = NextExternal; NextExternal = NextExternal->Next; } if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } }
void AcpiDmAddToExternalList ( ACPI_PARSE_OBJECT *Op, char *Path, UINT8 Type, UINT32 Value) { char *ExternalPath; char *Fullpath = NULL; ACPI_EXTERNAL_LIST *NewExternal; ACPI_EXTERNAL_LIST *NextExternal; ACPI_EXTERNAL_LIST *PrevExternal = NULL; ACPI_STATUS Status; if (!Path) { return; } /* Externalize the ACPI path */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, NULL, &ExternalPath); if (ACPI_FAILURE (Status)) { return; } /* Get the full pathname from root if "Path" has a parent prefix */ if (*Path == (UINT8) AML_PARENT_PREFIX) { Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath); if (Fullpath) { /* Set new external path */ ACPI_FREE (ExternalPath); ExternalPath = Fullpath; } } /* Check all existing externals to ensure no duplicates */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) { /* Duplicate method, check that the Value (ArgCount) is the same */ if ((NextExternal->Type == ACPI_TYPE_METHOD) && (NextExternal->Value != Value)) { ACPI_ERROR ((AE_INFO, "Argument count mismatch for method %s %u %u", NextExternal->Path, NextExternal->Value, Value)); } /* Allow upgrade of type from ANY */ else if (NextExternal->Type == ACPI_TYPE_ANY) { NextExternal->Type = Type; NextExternal->Value = Value; } ACPI_FREE (ExternalPath); return; } NextExternal = NextExternal->Next; } /* Allocate and init a new External() descriptor */ NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); if (!NewExternal) { ACPI_FREE (ExternalPath); return; } NewExternal->Path = ExternalPath; NewExternal->Type = Type; NewExternal->Value = Value; NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); /* Was the external path with parent prefix normalized to a fullpath? */ if (Fullpath == ExternalPath) { /* Get new internal path */ Status = AcpiNsInternalizeName (ExternalPath, &Path); if (ACPI_FAILURE (Status)) { ACPI_FREE (ExternalPath); ACPI_FREE (NewExternal); return; } /* Set flag to indicate External->InternalPath need to be freed */ NewExternal->Flags |= ACPI_IPATH_ALLOCATED; } NewExternal->InternalPath = Path; /* Link the new descriptor into the global list, alphabetically ordered */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0) { if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } NewExternal->Next = NextExternal; return; } PrevExternal = NextExternal; NextExternal = NextExternal->Next; } if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } }
void OptOptimizeNamePath ( ACPI_PARSE_OBJECT *Op, UINT32 Flags, ACPI_WALK_STATE *WalkState, char *AmlNameString, ACPI_NAMESPACE_NODE *TargetNode) { ACPI_STATUS Status; ACPI_BUFFER TargetPath; ACPI_BUFFER CurrentPath; ACPI_SIZE AmlNameStringLength; ACPI_NAMESPACE_NODE *CurrentNode; char *ExternalNameString; char *NewPath = NULL; ACPI_SIZE HowMuchShorter; ACPI_PARSE_OBJECT *NextOp; ACPI_FUNCTION_TRACE (OptOptimizeNamePath); /* This is an optional optimization */ if (!Gbl_ReferenceOptimizationFlag) { return_VOID; } /* Various required items */ if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent) { return_VOID; } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ", Op->Asl.LogicalLineNumber, AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); if (!(Flags & (AML_NAMED | AML_CREATE))) { if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) { /* We don't want to fuss with actual name declaration nodes here */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "******* NAME DECLARATION\n")); return_VOID; } } /* * The original path must be longer than one NameSeg (4 chars) for there * to be any possibility that it can be optimized to a shorter string */ AmlNameStringLength = strlen (AmlNameString); if (AmlNameStringLength <= ACPI_NAME_SIZE) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAMESEG %4.4s\n", AmlNameString)); return_VOID; } /* * We need to obtain the node that represents the current scope -- where * we are right now in the namespace. We will compare this path * against the Namepath, looking for commonality. */ CurrentNode = AcpiGbl_RootNode; if (WalkState->ScopeInfo) { CurrentNode = WalkState->ScopeInfo->Scope.Node; } if (Flags & (AML_NAMED | AML_CREATE)) { /* This is the declaration of a new name */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n")); /* * The node of interest is the parent of this node (the containing * scope). The actual namespace node may be up more than one level * of parse op or it may not exist at all (if we traverse back * up to the root.) */ NextOp = Op->Asl.Parent; while (NextOp && (!NextOp->Asl.Node)) { NextOp = NextOp->Asl.Parent; } if (NextOp && NextOp->Asl.Node) { CurrentNode = NextOp->Asl.Node; } else { CurrentNode = AcpiGbl_RootNode; } } else { /* This is a reference to an existing named object */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n")); } /* * Obtain the full paths to the two nodes that we are interested in * (Target and current namespace location) in external * format -- something we can easily manipulate */ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Target NamePath", ASL_NO_ABORT); return_VOID; } TargetPath.Length--; /* Subtract one for null terminator */ /* CurrentPath is the path to this scope (where we are in the namespace) */ CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Current NamePath", ASL_NO_ABORT); return_VOID; } CurrentPath.Length--; /* Subtract one for null terminator */ /* Debug output only */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString, NULL, &ExternalNameString); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Externalizing NamePath", ASL_NO_ABORT); return_VOID; } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n", (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer, (UINT32) TargetPath.Length, (char *) TargetPath.Pointer, ExternalNameString)); ACPI_FREE (ExternalNameString); /* * Attempt an optmization depending on the type of namepath */ if (Flags & (AML_NAMED | AML_CREATE)) { /* * This is a named opcode and the namepath is a name declaration, not * a reference. */ Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode, TargetNode, AmlNameString, &NewPath); if (ACPI_FAILURE (Status)) { /* * 2) now attempt to * optimize the namestring with carats (up-arrow) */ Status = OptBuildShortestPath (Op, WalkState, CurrentNode, TargetNode, &CurrentPath, &TargetPath, AmlNameStringLength, 1, &NewPath); } } else { /* * This is a reference to an existing named object * * 1) Check if search-to-root can be utilized using the last * NameSeg of the NamePath */ Status = OptSearchToRoot (Op, WalkState, CurrentNode, TargetNode, &TargetPath, &NewPath); if (ACPI_FAILURE (Status)) { /* * 2) Search-to-root could not be used, now attempt to * optimize the namestring with carats (up-arrow) */ Status = OptBuildShortestPath (Op, WalkState, CurrentNode, TargetNode, &CurrentPath, &TargetPath, AmlNameStringLength, 0, &NewPath); } } /* * Success from above indicates that the NamePath was successfully * optimized. We need to update the parse op with the new name */ if (ACPI_SUCCESS (Status)) { HowMuchShorter = (AmlNameStringLength - strlen (NewPath)); OptTotal += HowMuchShorter; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED BY %2u (TOTAL SAVED %2u)", (UINT32) HowMuchShorter, OptTotal)); if (Flags & AML_NAMED) { if (Op->Asl.AmlOpcode == AML_ALIAS_OP) { /* * ALIAS is the only oddball opcode, the name declaration * (alias name) is the second operand */ Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath; Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath); } else { Op->Asl.Child->Asl.Value.String = NewPath; Op->Asl.Child->Asl.AmlLength = strlen (NewPath); } } else if (Flags & AML_CREATE) { /* Name must appear as the last parameter */ NextOp = Op->Asl.Child; while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) { NextOp = NextOp->Asl.Next; } /* Update the parse node with the new NamePath */ NextOp->Asl.Value.String = NewPath; NextOp->Asl.AmlLength = strlen (NewPath); } else { /* Update the parse node with the new NamePath */ Op->Asl.Value.String = NewPath; Op->Asl.AmlLength = strlen (NewPath); } } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL")); } /* Cleanup path buffers */ ACPI_FREE (TargetPath.Pointer); ACPI_FREE (CurrentPath.Pointer); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n")); return_VOID; }
static ACPI_STATUS OptOptimizeNameDeclaration ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE *CurrentNode, ACPI_NAMESPACE_NODE *TargetNode, char *AmlNameString, char **NewPath) { ACPI_STATUS Status; char *NewPathExternal; ACPI_NAMESPACE_NODE *Node; ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration); if (((CurrentNode == AcpiGbl_RootNode) || (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK)) && (ACPI_IS_ROOT_PREFIX (AmlNameString[0]))) { /* * The current scope is the root, and the namepath has a root prefix * that is therefore extraneous. Remove it. */ *NewPath = &AmlNameString[1]; /* Debug output */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath, NULL, &NewPathExternal); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Externalizing NamePath", ASL_NO_ABORT); return (Status); } /* * Check to make sure that the optimization finds the node we are * looking for. This is simply a sanity check on the new * path that has been created. * * We know that we are at the root, so NULL is used for the scope. */ Status = AcpiNsLookup (NULL, *NewPath, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node)); if (ACPI_SUCCESS (Status)) { /* Found the namepath, but make sure the node is correct */ if (Node == TargetNode) { /* The lookup matched the node, accept this optimization */ AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION, Op, NewPathExternal); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "AT ROOT: %-24s", NewPathExternal)); } else { /* Node is not correct, do not use this optimization */ Status = AE_NOT_FOUND; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE")); AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, "Not using optimized name - found wrong node"); } } else { /* The lookup failed, we obviously cannot use this optimization */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND")); AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, "Not using optimized name - did not find node"); } ACPI_FREE (NewPathExternal); return (Status); } /* Could not optimize */ return (AE_NOT_FOUND); }
static ACPI_STATUS AcpiDmFindOrphanDescending ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { const ACPI_OPCODE_INFO *OpInfo; ACPI_PARSE_OBJECT *ChildOp; ACPI_PARSE_OBJECT *NextOp; ACPI_PARSE_OBJECT *ParentOp; UINT32 ArgCount; if (!Op) { return (AE_OK); } OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); switch (Op->Common.AmlOpcode) { #ifdef ACPI_UNDER_DEVELOPMENT case AML_ADD_OP: ChildOp = Op->Common.Value.Arg; if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && !ChildOp->Common.Node) { AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String, NULL, &Path); AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s */\n", Op->Common.AmlOpName, Path); ACPI_FREE (Path); NextOp = Op->Common.Next; if (!NextOp) { /* This NamePath has no args, assume it is an integer */ AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); return (AE_OK); } ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp); AcpiOsPrintf ("/* A-CHILDREN: %d Actual %d */\n", ArgCount, AcpiDmCountChildren (Op)); if (ArgCount < 1) { /* One Arg means this is just a Store(Name,Target) */ AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); return (AE_OK); } AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); } break; #endif case AML_STORE_OP: ChildOp = Op->Common.Value.Arg; if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && !ChildOp->Common.Node) { NextOp = Op->Common.Next; if (!NextOp) { /* This NamePath has no args, assume it is an integer */ AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); return (AE_OK); } ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp); if (ArgCount <= 1) { /* One Arg means this is just a Store(Name,Target) */ AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0); return (AE_OK); } AcpiDmAddToExternalList (ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); } break; case AML_INT_NAMEPATH_OP: /* Must examine parent to see if this namepath is an argument */ ParentOp = Op->Common.Parent; OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); if ((OpInfo->Class != AML_CLASS_EXECUTE) && (OpInfo->Class != AML_CLASS_CREATE) && (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && !Op->Common.Node) { ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next); /* * Check if namepath is a predicate for if/while or lone parameter to * a return. */ if (ArgCount == 0) { if (((ParentOp->Common.AmlOpcode == AML_IF_OP) || (ParentOp->Common.AmlOpcode == AML_WHILE_OP) || (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) && /* And namepath is the first argument */ (ParentOp->Common.Value.Arg == Op)) { AcpiDmAddToExternalList (Op->Common.Value.String, ACPI_TYPE_INTEGER, 0); break; } } /* * This is a standalone namestring (not a parameter to another * operator) - it *must* be a method invocation, nothing else is * grammatically possible. */ AcpiDmAddToExternalList (Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount); } break; default: break; } return (AE_OK); }
static ACPI_STATUS AcpiDmDumpDescending ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; char *Path; if (!Op) { return (AE_OK); } OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); Info->Count++; /* Most of the information (count, level, name) here */ AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); AcpiDmIndent (Level); AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); /* Extra info is helpful */ switch (Op->Common.AmlOpcode) { case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer); break; case AML_INT_NAMEPATH_OP: if (Op->Common.Value.String) { AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, NULL, &Path); AcpiOsPrintf ("%s %p", Path, Op->Common.Node); ACPI_FREE (Path); } else { AcpiOsPrintf ("[NULL]"); } break; case AML_NAME_OP: case AML_METHOD_OP: case AML_DEVICE_OP: case AML_INT_NAMEDFIELD_OP: AcpiOsPrintf ("%4.4s", &Op->Named.Name); break; default: break; } AcpiOsPrintf ("\n"); return (AE_OK); }
void AcpiDmAddOpToExternalList ( ACPI_PARSE_OBJECT *Op, char *Path, UINT8 Type, UINT32 Value, UINT16 Flags) { char *ExternalPath; char *InternalPath = Path; char *Temp; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (DmAddOpToExternalList); if (!Path) { return_VOID; } /* Remove a root backslash if present */ if ((*Path == AML_ROOT_PREFIX) && (Path[1])) { Path++; } /* Externalize the pathname */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, NULL, &ExternalPath); if (ACPI_FAILURE (Status)) { return_VOID; } /* * Get the full pathname from the root if "Path" has one or more * parent prefixes (^). Note: path will not contain a leading '\'. */ if (*Path == (UINT8) AML_PARENT_PREFIX) { Temp = AcpiDmNormalizeParentPrefix (Op, ExternalPath); /* Set new external path */ ACPI_FREE (ExternalPath); ExternalPath = Temp; if (!Temp) { return_VOID; } /* Create the new internal pathname */ Flags |= ACPI_EXT_INTERNAL_PATH_ALLOCATED; Status = AcpiNsInternalizeName (ExternalPath, &InternalPath); if (ACPI_FAILURE (Status)) { ACPI_FREE (ExternalPath); return_VOID; } } /* Create the new External() declaration node */ Status = AcpiDmCreateNewExternal (ExternalPath, InternalPath, Type, Value, Flags); if (ACPI_FAILURE (Status)) { ACPI_FREE (ExternalPath); if (Flags & ACPI_EXT_INTERNAL_PATH_ALLOCATED) { ACPI_FREE (InternalPath); } } return_VOID; }
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; char *ExternalPath; 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_INTERPRETER_MODE LocalInterpreterMode; 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. Externalize * the internal path for error message. */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Pathname, NULL, &ExternalPath); if (ACPI_SUCCESS (Status)) { ACPI_ERROR ((AE_INFO, "%s: Path has too many parent prefixes (^)", ExternalPath)); ACPI_FREE (ExternalPath); } 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: /* 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; } } /* Handle opcodes that create a new NameSeg via a full NamePath */ LocalInterpreterMode = InterpreterMode; if ((Flags & ACPI_NS_PREFIX_MUST_EXIST) && (NumSegments > 0)) { /* Every element of the path must exist (except for the final NameSeg) */ LocalInterpreterMode = ACPI_IMODE_EXECUTE; } /* 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, LocalInterpreterMode, ThisSearchType, LocalFlags, &ThisNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { #if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */ if (Flags & ACPI_NS_PREFIX_MUST_EXIST) { AcpiOsPrintf (ACPI_MSG_BIOS_ERROR "Object does not exist: %4.4s\n", &SimpleName); } #endif /* 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)); } #ifdef ACPI_EXEC_APP if ((Status == AE_ALREADY_EXISTS) && (ThisNode->Flags & ANOBJ_NODE_EARLY_INIT)) { ThisNode->Flags &= ~ANOBJ_NODE_EARLY_INIT; Status = AE_OK; } #endif #ifdef ACPI_ASL_COMPILER /* * If this ACPI name already exists within the namespace as an * external declaration, then mark the external as a conflicting * declaration and proceed to process the current node as if it did * not exist in the namespace. If this node is not processed as * normal, then it could cause improper namespace resolution * by failing to open a new scope. */ if (AcpiGbl_DisasmFlag && (Status == AE_ALREADY_EXISTS) && ((ThisNode->Flags & ANOBJ_IS_EXTERNAL) || (WalkState && WalkState->Opcode == AML_EXTERNAL_OP))) { ThisNode->Flags &= ~ANOBJ_IS_EXTERNAL; ThisNode->Type = (UINT8)ThisSearchType; if (WalkState->Opcode != AML_EXTERNAL_OP) { AcpiDmMarkExternalConflict (ThisNode); } break; } #endif *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_NAMESEG_SIZE; CurrentNode = ThisNode; }
void AcpiDmAddToExternalList ( char *Path, UINT8 Type, UINT32 Value) { char *ExternalPath; ACPI_EXTERNAL_LIST *NewExternal; ACPI_EXTERNAL_LIST *NextExternal; ACPI_EXTERNAL_LIST *PrevExternal = NULL; ACPI_STATUS Status; if (!Path) { return; } /* Externalize the ACPI path */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path, NULL, &ExternalPath); if (ACPI_FAILURE (Status)) { return; } /* Ensure that we don't have duplicate externals */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { /* Allow upgrade of type from ANY */ if (!ACPI_STRCMP (ExternalPath, NextExternal->Path)) { /* Duplicate method, check that the Value (ArgCount) is the same */ if ((NextExternal->Type == ACPI_TYPE_METHOD) && (NextExternal->Value != Value)) { ACPI_ERROR ((AE_INFO, "Argument count mismatch for method %s %d %d", NextExternal->Path, NextExternal->Value, Value)); } if (NextExternal->Type == ACPI_TYPE_ANY) { NextExternal->Type = Type; NextExternal->Value = Value; } ACPI_FREE (ExternalPath); return; } NextExternal = NextExternal->Next; } /* Allocate and init a new External() descriptor */ NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST)); NewExternal->InternalPath = Path; NewExternal->Path = ExternalPath; NewExternal->Type = Type; NewExternal->Value = Value; NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); /* Link the new descriptor into the global list, ordered by string length */ NextExternal = AcpiGbl_ExternalList; while (NextExternal) { if (NewExternal->Length <= NextExternal->Length) { if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } NewExternal->Next = NextExternal; return; } PrevExternal = NextExternal; NextExternal = NextExternal->Next; } if (PrevExternal) { PrevExternal->Next = NewExternal; } else { AcpiGbl_ExternalList = NewExternal; } }
char * AcpiNsBuildPrefixedPathname ( ACPI_GENERIC_STATE *PrefixScope, const char *InternalPath) { ACPI_STATUS Status; char *FullPath = NULL; char *ExternalPath = NULL; char *PrefixPath = NULL; UINT32 PrefixPathLength = 0; /* If there is a prefix, get the pathname to it */ if (PrefixScope && PrefixScope->Scope.Node) { PrefixPath = AcpiNsGetNormalizedPathname (PrefixScope->Scope.Node, TRUE); if (PrefixPath) { PrefixPathLength = strlen (PrefixPath); } } Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, NULL, &ExternalPath); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Merge the prefix path and the path. 2 is for one dot and trailing null */ FullPath = ACPI_ALLOCATE_ZEROED ( PrefixPathLength + strlen (ExternalPath) + 2); if (!FullPath) { goto Cleanup; } /* Don't merge if the External path is already fully qualified */ if (PrefixPath && (*ExternalPath != '\\') && (*ExternalPath != '^')) { strcat (FullPath, PrefixPath); if (PrefixPath[1]) { strcat (FullPath, "."); } } AcpiNsNormalizePathname (ExternalPath); strcat (FullPath, ExternalPath); Cleanup: if (PrefixPath) { ACPI_FREE (PrefixPath); } if (ExternalPath) { ACPI_FREE (ExternalPath); } return (FullPath); }