diff options
Diffstat (limited to 'source/common/dmextern.c')
| -rw-r--r-- | source/common/dmextern.c | 326 |
1 files changed, 321 insertions, 5 deletions
diff --git a/source/common/dmextern.c b/source/common/dmextern.c index e74311701bc4..b78304067f19 100644 --- a/source/common/dmextern.c +++ b/source/common/dmextern.c @@ -46,7 +46,9 @@ #include "amlcode.h" #include "acnamesp.h" #include "acdisasm.h" +#include "aslcompiler.h" #include <stdio.h> +#include <errno.h> /* @@ -87,6 +89,8 @@ static const char *AcpiGbl_DmTypeNames[] = /* 19 */ ", FieldUnitObj" }; +#define METHOD_SEPARATORS " \t,()\n" + /* Local prototypes */ @@ -99,6 +103,12 @@ AcpiDmNormalizeParentPrefix ( ACPI_PARSE_OBJECT *Op, char *Path); +static void +AcpiDmAddToExternalListFromFile ( + char *Path, + UINT8 Type, + UINT32 Value); + /******************************************************************************* * @@ -444,7 +454,7 @@ AcpiDmAddToExternalList ( (NextExternal->Value != Value)) { ACPI_ERROR ((AE_INFO, - "Argument count mismatch for method %s %u %u", + "External method arg count mismatch %s: Current %u, attempted %u", NextExternal->Path, NextExternal->Value, Value)); } @@ -536,6 +546,275 @@ AcpiDmAddToExternalList ( /******************************************************************************* * + * FUNCTION: AcpiDmGetExternalsFromFile + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Process the optional external reference file. + * + * Each line in the file should be of the form: + * External (<Method namepath>, MethodObj, <ArgCount>) + * + * Example: + * External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4) + * + ******************************************************************************/ + +void +AcpiDmGetExternalsFromFile ( + void) +{ + FILE *ExternalRefFile; + char *Token; + char *MethodName; + UINT32 ArgCount; + UINT32 ImportCount = 0; + + + if (!Gbl_ExternalRefFilename) + { + return; + } + + /* Open the file */ + + ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r"); + if (!ExternalRefFile) + { + fprintf (stderr, "Could not open external reference file \"%s\"\n", + Gbl_ExternalRefFilename); + return; + } + + /* Each line defines a method */ + + while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile)) + { + Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */ + if (!Token) continue; + if (strcmp (Token, "External")) continue; + + MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */ + if (!MethodName) continue; + + Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */ + if (!Token) continue; + if (strcmp (Token, "MethodObj")) continue; + + Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */ + if (!Token) continue; + + /* Convert arg count string to an integer */ + + errno = 0; + ArgCount = strtoul (Token, NULL, 0); + if (errno) + { + fprintf (stderr, "Invalid argument count (%s)\n", Token); + continue; + } + if (ArgCount > 7) + { + fprintf (stderr, "Invalid argument count (%u)\n", ArgCount); + continue; + } + + /* Add this external to the global list */ + + AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n", + Gbl_ExternalRefFilename, ArgCount, MethodName); + + AcpiDmAddToExternalListFromFile (MethodName, ACPI_TYPE_METHOD, ArgCount | 0x80); + ImportCount++; + } + + if (!ImportCount) + { + fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n", + Gbl_ExternalRefFilename); + } + else + { + /* Add the external(s) to the namespace */ + + AcpiDmAddExternalsToNamespace (); + + AcpiOsPrintf ("%s: Imported %u external method definitions\n", + Gbl_ExternalRefFilename, ImportCount); + } + + fclose (ExternalRefFile); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDmAddToExternalListFromFile + * + * PARAMETERS: Path - Internal (AML) path to the object + * Type - ACPI object type to be added + * Value - Arg count if adding a Method object + * + * RETURN: None + * + * DESCRIPTION: Insert a new name into the global list of Externals which + * will in turn be later emitted as an External() declaration + * in the disassembled output. + * + ******************************************************************************/ + +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; + } +} + + +/******************************************************************************* + * * FUNCTION: AcpiDmAddExternalsToNamespace * * PARAMETERS: None @@ -563,7 +842,7 @@ AcpiDmAddExternalsToNamespace ( Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, ACPI_IMODE_LOAD_PASS1, - ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, + ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); if (ACPI_FAILURE (Status)) @@ -731,7 +1010,8 @@ AcpiDmEmitExternals ( NextExternal->Path, AcpiDmGetObjectTypeName (NextExternal->Type)); - AcpiOsPrintf (") // Warning: Unresolved Method, " + AcpiOsPrintf ( + ") // Warning: Unresolved Method, " "guessing %u arguments (may be incorrect, see warning above)\n", NextExternal->Value); @@ -743,9 +1023,45 @@ AcpiDmEmitExternals ( AcpiOsPrintf ("\n"); + + /* Emit externals that were imported from a file */ + + if (Gbl_ExternalRefFilename) + { + AcpiOsPrintf ( + " /*\n * External declarations that were imported from\n" + " * the reference file [%s]\n */\n", + Gbl_ExternalRefFilename); + + NextExternal = AcpiGbl_ExternalList; + while (NextExternal) + { + if (!NextExternal->Emitted && (NextExternal->Flags & ACPI_FROM_REFERENCE_FILE)) + { + AcpiOsPrintf (" External (%s%s", + NextExternal->Path, + AcpiDmGetObjectTypeName (NextExternal->Type)); + + if (NextExternal->Type == ACPI_TYPE_METHOD) + { + AcpiOsPrintf (") // %u Arguments\n", + NextExternal->Value); + } + else + { + AcpiOsPrintf (")\n"); + } + NextExternal->Emitted = TRUE; + } + + NextExternal = NextExternal->Next; + } + + AcpiOsPrintf ("\n"); + } + /* - * Walk the list of externals (unresolved references) - * found during the AML parsing + * Walk the list of externals found during the AML parsing */ while (AcpiGbl_ExternalList) { |
