iASL/disassembler: Add support for external method reference file.

Adds the -fe option which allows the user to specify a file that
contains control method external declarations, with the proper
number of arguments. This tells the disassembler how to parse
code that invokes these methods.
This commit is contained in:
Robert Moore 2013-07-26 09:46:13 -07:00
parent 0631bf977d
commit 96f37ef6bf
8 changed files with 366 additions and 12 deletions

View File

@ -413,6 +413,10 @@ AdAmlDisassemble (
{
AcpiDmClearExternalList ();
}
/* Load any externals defined in the optional external ref file */
AcpiDmGetExternalsFromFile ();
}
else
{

View File

@ -445,10 +445,18 @@ AcpiDmDumpDescending (
switch (Op->Common.AmlOpcode)
{
case AML_BYTE_OP:
AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
break;
case AML_WORD_OP:
AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
break;
case AML_DWORD_OP:
AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer);
AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
break;
case AML_QWORD_OP:

View File

@ -118,7 +118,9 @@
#include "amlcode.h"
#include "acnamesp.h"
#include "acdisasm.h"
#include "aslcompiler.h"
#include <stdio.h>
#include <errno.h>
/*
@ -159,6 +161,8 @@ static const char *AcpiGbl_DmTypeNames[] =
/* 19 */ ", FieldUnitObj"
};
#define METHOD_SEPARATORS " \t,()\n"
/* Local prototypes */
@ -171,6 +175,12 @@ AcpiDmNormalizeParentPrefix (
ACPI_PARSE_OBJECT *Op,
char *Path);
static void
AcpiDmAddToExternalListFromFile (
char *Path,
UINT8 Type,
UINT32 Value);
/*******************************************************************************
*
@ -516,7 +526,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));
}
@ -606,6 +616,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
@ -635,7 +914,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))
@ -803,7 +1082,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);
@ -815,9 +1095,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)
{

View File

@ -258,6 +258,7 @@ ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_IncludeFilename, NULL)
ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_OutputFilenamePrefix, NULL);
ASL_EXTERN ASL_INCLUDE_DIR ASL_INIT_GLOBAL (*Gbl_IncludeDirList, NULL);
ASL_EXTERN char *Gbl_CurrentInputFilename;
ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_ExternalRefFilename, NULL);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HasIncludeFiles, FALSE);

View File

@ -210,6 +210,7 @@ Usage (
ACPI_OPTION ("-dc <f1,f2>", "Disassemble AML and immediately compile it");
ACPI_OPTION ("", " (Obtain DSDT from current system if no input file)");
ACPI_OPTION ("-e <f1,f2>", "Include ACPI table(s) for external symbol resolution");
ACPI_OPTION ("-fe <file>", "Specify external symbol declaration file");
ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)");
ACPI_OPTION ("-in", "Ignore NoOp opcodes");
ACPI_OPTION ("-vt", "Dump binary table data in hex format within output file");

View File

@ -140,7 +140,7 @@ AslDoResponseFile (
#define ASL_TOKEN_SEPARATORS " \t\n"
#define ASL_SUPPORTED_OPTIONS "@:b|c|d^D:e:fgh^i|I:l^m:no|p:P^r:s|t|T+G^v^w|x:z"
#define ASL_SUPPORTED_OPTIONS "@:b|c|d^D:e:f^gh^i|I:l^m:no|p:P^r:s|t|T+G^v^w|x:z"
/*******************************************************************************
@ -208,8 +208,7 @@ AslCommandLine (
if (BadCommandLine)
{
printf ("\n");
Usage ();
printf ("Use -h option for help information\n");
exit (1);
}
@ -348,9 +347,30 @@ AslDoOptions (
}
break;
case 'f': /* Ignore errors and force creation of aml file */
case 'f':
Gbl_IgnoreErrors = TRUE;
switch (AcpiGbl_Optarg[0])
{
case '^': /* Ignore errors and force creation of aml file */
Gbl_IgnoreErrors = TRUE;
break;
case 'e': /* Disassembler: Get external declaration file */
if (AcpiGetoptArgument (argc, argv))
{
return (-1);
}
Gbl_ExternalRefFilename = AcpiGbl_Optarg;
break;
default:
printf ("Unknown option: -f%s\n", AcpiGbl_Optarg);
return (-1);
}
break;
case 'G':

View File

@ -766,6 +766,9 @@ void
AcpiDmUnresolvedWarning (
UINT8 Type);
void
AcpiDmGetExternalsFromFile (
void);
/*
* dmresrc

View File

@ -1289,7 +1289,8 @@ typedef struct acpi_external_list
/* Values for Flags field above */
#define ACPI_IPATH_ALLOCATED 0x01
#define ACPI_IPATH_ALLOCATED 0x01
#define ACPI_FROM_REFERENCE_FILE 0x02
typedef struct acpi_external_file