windows-nt/Source/XPSP1/NT/base/busdrv/acpi/tools/unasm2/unasm.c

2006 lines
38 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
unasm.c
Abstract:
This unassembles an AML file
Author:
Based on code by Mike Tsang (MikeTs)
Stephane Plante (Splante)
Environment:
User mode only
Revision History:
--*/
#include "pch.h"
ULONG DSDTLoaded = FALSE;
UCHAR
LOCAL
ComputeDataCheckSum(
PUCHAR OpCode,
ULONG Length
)
/*++
Routine Description:
This routine performs a data check sum on the supplied opcode pointer
Arguments:
OpCode - Data Buffer
Length - Number of bytes in buffer
Return Value:
UCHAR
--*/
{
UCHAR checkSum = 0;
while (Length > 0) {
checkSum += *OpCode;
OpCode++;
Length--;
}
return checkSum;
}
DllInit(
HANDLE Module,
ULONG Reason,
ULONG Reserved
)
/*++
Routine Description:
This routine is called to initialize the DLL
Arguments:
Return Value:
--*/
{
switch (Reason) {
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
VOID
LOCAL
DumpCode(
PUCHAR *Opcode,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
This routine doesn't do much right now, but it is the point where
raw bytes should be displayed as well as the unassembly
Arguments:
OpCode - Pointer to the OpCode
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
if (PrintFunction != NULL) {
PrintFunction("\n");
}
}
PASLTERM
LOCAL
FindKeywordTerm(
UCHAR KeyWordGroup,
UCHAR Data
)
/*++
Routine Description:
Find a Keyword within the TermTable
Arguments:
KeyWordGroup - What to search for
Data - Data to match keyword
Return Value:
PASLTERM
--*/
{
PASLTERM term = NULL;
ULONG i;
for (i = 0; TermTable[i].ID != NULL; i++) {
if ((TermTable[i].TermClass == TC_KEYWORD) &&
(TermTable[i].ArgActions[0] == KeyWordGroup) &&
((Data & (UCHAR)(TermTable[i].TermData >> 8)) ==
(UCHAR)(TermTable[i].TermData & 0xff))) {
break;
}
}
if (TermTable[i].ID != NULL) {
term = &TermTable[i];
}
return term;
}
UCHAR
LOCAL
FindOpClass(
UCHAR OpCode,
POPMAP OpCodeTable
)
/*++
Routine Description:
Find opcode class of extended opcode
Arguments:
OpCode - The Opcode to look up
OpCodeTable - The table to look in
Return Value:
UCHAR
--*/
{
UCHAR opCodeClass = OPCLASS_INVALID;
while (OpCodeTable->OpCodeClass != 0) {
if (OpCode == OpCodeTable->ExtendedOpCode) {
opCodeClass = OpCodeTable->OpCodeClass;
break;
}
OpCodeTable++;
}
return opCodeClass;
}
PASLTERM
LOCAL
FindOpTerm(
ULONG OpCode
)
/*++
Routine Description:
Find an OpCode within the TermTable
Arguments:
OpCode - What to look for in the TermTable
Return Value:
PASLTERM
--*/
{
PASLTERM term = NULL;
ULONG i;
for (i = 0; TermTable[i].ID != NULL; i++) {
if ( (TermTable[i].OpCode == OpCode) &&
(TermTable[i].TermClass & TC_OPCODE_TERM) ) {
break;
}
}
if (TermTable[i].ID != NULL) {
term = &TermTable[i];
}
return term;
}
ULONG
EXPORT
IsDSDTLoaded(
VOID
)
/*++
Routine Description:
This routine returns wether or not we have loaded a DSDT image
Arguments:
None
Return:
ULONG
--*/
{
return DSDTLoaded;
}
NTSTATUS
LOCAL
ParseNameTail(
PUCHAR *OpCode,
PUCHAR Buffer,
ULONG Length
)
/*++
Routine Description:
Parse AML name tail
Arguments:
OpCode - Pointer to the OpCode
Buffer - Where to hold the parsed named
Length - Index to the tail of Buffer
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG numSegments = 0;
//
// We do not check for invalid NameSeg characters here and assume that
// the compiler does its job not generating it.
//
if (**OpCode == '\0'){
//
// There is no NameTail (i.e. either NULL name or name with just
// prefixes.
//
(*OpCode)++;
} else if (**OpCode == OP_MULTI_NAME_PREFIX) {
(*OpCode)++;
numSegments = (ULONG)**OpCode;
(*OpCode)++;
} else if (**OpCode == OP_DUAL_NAME_PREFIX) {
(*OpCode)++;
numSegments = 2;
} else {
numSegments = 1;
}
while ((numSegments > 0) && (Length + sizeof(NAMESEG) < MAX_NAME_LEN)) {
strncpy(&Buffer[Length], (PUCHAR)(*OpCode), sizeof(NAMESEG));
Length += sizeof(NAMESEG);
*OpCode += sizeof(NAMESEG);
numSegments--;
if ((numSegments > 0) && (Length + 1 < MAX_NAME_LEN)) {
Buffer[Length] = '.';
Length++;
}
}
if (numSegments > 0) {
status = STATUS_NAME_TOO_LONG;
} else {
Buffer[Length] = '\0';
}
return status;
}
ULONG
LOCAL
ParsePackageLen(
PUCHAR *OpCode,
PUCHAR *OpCodeNext
)
/*++
Routine Description:
Parses the packages length
Arguments:
OpCode - Pointer to the current instruction
OpCodeNode - Where to hold a pointer to the next instruction
Return Value:
ULONG - Package Length
--*/
{
UCHAR noBytes;
UCHAR i;
ULONG length;
if (OpCodeNext != NULL) {
*OpCodeNext = *OpCode;
}
length = (ULONG)(**OpCode);
(*OpCode)++;
noBytes = (UCHAR)((length & 0xc0) >> 6);
if (noBytes != 0) {
length &= 0x0000000f;
for (i = 0; i < noBytes; i++) {
length |= (ULONG)(**OpCode) << (i*8 + 4);
(*OpCode)++;
}
}
if (OpCodeNext != NULL) {
*OpCodeNext += length;
}
return length;
}
VOID
LOCAL
PrintIndent(
PUNASM_PRINT PrintFunction,
ULONG IndentLevel
)
/*++
Routine Description:
Does the indenting required
Arguments:
PrintFunction - Function to call to indent
IndentLevel - How many levels to indent
Return Value:
VOID
--*/
{
ULONG i;
for (i = 0; i < IndentLevel; i++) {
PrintFunction(" ");
}
}
NTSTATUS
LOCAL
UnAsmArgs(
PUCHAR UnAsmArgTypes,
PUCHAR ArgActions,
PUCHAR *OpCode,
PNSOBJ *NameObject,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble Arguments:
Arguments:
UnAsmArgTypes - UnAsm ArgTypes String
ArgActions - Arg Action Types
OpCode - Pointer to the OpCode
NameObject - To hold created object
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PASLTERM term;
static UCHAR argData = 0;
ULONG i;
ULONG numArgs;
numArgs = strlen(UnAsmArgTypes);
if (PrintFunction != NULL) {
PrintFunction("(");
}
for (i = 0; i < numArgs; i++){
if ((i != 0) && (PrintFunction != NULL)) {
PrintFunction(", ");
}
switch (UnAsmArgTypes[i]) {
case 'N':
ASSERT(ArgActions != NULL);
status = UnAsmNameObj(
OpCode,
(islower(ArgActions[i])? NameObject: NULL),
ArgActions[i],
PrintFunction,
BaseAddress,
IndentLevel
);
break;
case 'O':
if ((**OpCode == OP_BUFFER) || (**OpCode == OP_PACKAGE) ||
(OpClassTable[**OpCode] == OPCLASS_CONST_OBJ)) {
term = FindOpTerm( (ULONG)(**OpCode) );
ASSERT(term != NULL);
(*OpCode)++;
status = UnAsmTermObj(
term,
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
} else {
status = UnAsmDataObj(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel);
}
break;
case 'C':
status = UnAsmOpcode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
break;
case 'B':
if (PrintFunction != NULL) {
PrintFunction("0x%x", **OpCode);
}
*OpCode += sizeof(UCHAR);
break;
case 'K':
case 'k':
if (UnAsmArgTypes[i] == 'K') {
argData = **OpCode;
}
if ((ArgActions != NULL) && (ArgActions[i] == '!')) {
if (*NameObject != NULL) {
(*NameObject)->ObjectData.DataValue =
(ULONG)(**OpCode & 0x07);
}
if (PrintFunction != NULL) {
PrintFunction("0x%x", **OpCode & 0x07);
}
} else if (PrintFunction != NULL) {
term = FindKeywordTerm(ArgActions[i], argData);
ASSERT(term != NULL);
PrintFunction("%s", term->ID);
}
if (UnAsmArgTypes[i] == 'K') {
*OpCode += sizeof(UCHAR);
}
break;
case 'W':
if (PrintFunction != NULL) {
PrintFunction("0x%x", *( (PUSHORT)*OpCode ) );
}
*OpCode += sizeof(USHORT);
break;
case 'D':
if (PrintFunction != NULL) {
PrintFunction("0x%x", *( (PULONG)*OpCode ) );
}
*OpCode += sizeof(ULONG);
break;
case 'S':
ASSERT(ArgActions != NULL);
status = UnAsmSuperName(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
break;
default:
status = STATUS_ACPI_INVALID_ARGTYPE;
}
}
if (PrintFunction != NULL) {
PrintFunction(")");
}
return status;
}
NTSTATUS
LOCAL
UnAsmDataList(
PUCHAR *OpCode,
PUCHAR OpCodeEnd,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble Data List
Arguments:
OpCode - Pointer to the OpCode
OpCodeEnd - End of List
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG i;
//
// This is another place that DumpCode() was being called from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("{\n");
}
while (*OpCode < OpCodeEnd) {
if (PrintFunction != NULL) {
PrintFunction("\t0x%02x", **OpCode);
}
(*OpCode)++;
for (i = 1; (*OpCode < OpCodeEnd) && (i < 12); ++i) {
if (PrintFunction != NULL) {
PrintFunction(", 0x%02x", **OpCode);
}
(*OpCode)++;
}
if (PrintFunction != NULL) {
if (*OpCode < OpCodeEnd) {
PrintFunction(",");
}
PrintFunction("\n");
}
}
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("}");
}
return status;
}
NTSTATUS
LOCAL
UnAsmDataObj(
PUCHAR *OpCode,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassembles a data object
Arguments:
OpCode - Pointer to the OpCode
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
UCHAR localOpcode = **OpCode;
(*OpCode)++;
switch (localOpcode)
{
case OP_BYTE:
if (PrintFunction != NULL)
{
PrintFunction("0x%x", **OpCode);
}
*OpCode += sizeof(UCHAR);
break;
case OP_WORD:
if (PrintFunction != NULL)
{
PrintFunction("0x%x", *((PUSHORT)*OpCode));
}
*OpCode += sizeof(USHORT);
break;
case OP_DWORD:
if (PrintFunction != NULL)
{
PrintFunction("0x%x", *((PULONG)*OpCode));
}
*OpCode += sizeof(ULONG);
break;
case OP_STRING:
if (PrintFunction != NULL)
{
PrintFunction("\"%s\"", *OpCode);
}
*OpCode += strlen((PUCHAR)*OpCode) + 1;
break;
default:
status = STATUS_ACPI_INVALID_OPCODE;
}
return status;
}
NTSTATUS
EXPORT
UnAsmDSDT(
PUCHAR DSDT,
PUNASM_PRINT PrintFunction,
ULONG_PTR DsdtLocation,
ULONG IndentLevel
)
/*++
Routine Description:
This routine unassembles an entire DSDT table
Arguments:
DSDT - Where the DSDT is located in memory
PrintFunction - What function to call to print to the user
DsdtLocation - Where the DSDT is located in memory
IndentLevel - How much space to indent from the left margin
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDESCRIPTION_HEADER header = (PDESCRIPTION_HEADER) DSDT;
ASSERT(RootNameSpaceObject != NULL);
CurrentOwnerNameSpaceObject = NULL;
CurrentScopeNameSpaceObject = RootNameSpaceObject;
TopOpcode = CurrentOpcode = DSDT;
//
// Dump the header
//
status = UnAsmHeader( header, PrintFunction, DsdtLocation, IndentLevel );
if (NT_SUCCESS(status)) {
DSDT += sizeof(DESCRIPTION_HEADER);
status = UnAsmScope(
&DSDT,
(PUCHAR) (DSDT + header->Length - sizeof(DESCRIPTION_HEADER)),
PrintFunction,
DsdtLocation,
IndentLevel
);
}
return status;
}
NTSTATUS
LOCAL
UnAsmField(
PUCHAR *OpCode,
PULONG BitPos,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble field
Arguments:
OpCode - Pointer to the OpCode
OpCodeEnd - End of List
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
if (**OpCode == 0x01) {
(*OpCode)++;
if (PrintFunction != NULL) {
PASLTERM term;
term = FindKeywordTerm('A', **OpCode);
PrintFunction(
"AccessAs(%s, 0x%x)",
term->ID,
*(*OpCode + 1)
);
}
*OpCode += 2;
} else {
UCHAR nameSeg[sizeof(NAMESEG) + 1];
ULONG length;
if (**OpCode == 0) {
nameSeg[0] = '\0';
(*OpCode)++;
} else {
strncpy(nameSeg, (PUCHAR)*OpCode, sizeof(NAMESEG));
nameSeg[sizeof(NAMESEG)] = '\0';
*OpCode += sizeof(NAMESEG);
}
length = ParsePackageLen(
OpCode,
NULL
);
if (nameSeg[0] == '\0') {
if (PrintFunction != NULL) {
if ((length > 32) && (((*BitPos + length) % 8) == 0)) {
PrintFunction(
"Offset(0x%x)",
(*BitPos + length)/8
);
} else {
PrintFunction(
", %d",
length
);
}
}
} else {
if (PrintFunction != NULL) {
PrintFunction(
"%s, %d",
nameSeg,
length
);
}
if (PrintFunction == NULL) {
status = CreateObject(
nameSeg,
NSTYPE_FIELDUNIT,
NULL
);
}
}
*BitPos += length;
}
return status;
}
NTSTATUS
LOCAL
UnAsmFieldList(
PUCHAR *OpCode,
PUCHAR OpCodeEnd,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble field list
Arguments:
OpCode - Pointer to the OpCode
OpCodeEnd - End of List
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG bitPos = 0;
//
// This is another place that DumpCode() was being called from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("{\n");
}
IndentLevel++;
while ((*OpCode < OpCodeEnd) && NT_SUCCESS(status)) {
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
}
status = UnAsmField(
OpCode,
&bitPos,
PrintFunction,
BaseAddress,
IndentLevel
);
if (NT_SUCCESS(status) && (*OpCode < OpCodeEnd) &&
(PrintFunction != NULL) ) {
PrintFunction(",");
}
//
// This is another place that DumpCode() was being called from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
}
IndentLevel--;
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("}");
}
return status;
}
NTSTATUS
LOCAL
UnAsmHeader(
PDESCRIPTION_HEADER DsdtHeader,
PUNASM_PRINT PrintFunction,
ULONG_PTR DsdtLocation,
ULONG IndentLevel
)
/*++
Routine Description:
Unassembles the DSDT header
Arguments:
DsdtHeader - Header to unassemble
PrintFunction - Function to call to display information
DsdtLocation - Where in memory the DSDT Lives
IndentLevel - How much space to indent from the left margin
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
UCHAR signature[sizeof(DsdtHeader->Signature) + 1] = {0};
UCHAR oemID[sizeof(DsdtHeader->OEMID) + 1] = {0};
UCHAR oemTableID[sizeof(DsdtHeader->OEMTableID) + 1] = {0};
UCHAR creatorID[sizeof(DsdtHeader->CreatorID) + 1] = {0};
UCHAR checkSum;
//
// Lets do a checksump on the entire table
//
checkSum = ComputeDataCheckSum(
(PUCHAR) DsdtHeader,
DsdtHeader->Length
);
if (checkSum != 0) {
status = STATUS_ACPI_INVALID_TABLE;
}
strncpy(
signature,
(PUCHAR)&DsdtHeader->Signature,
sizeof(DsdtHeader->Signature)
);
strncpy(
oemID,
(PUCHAR) DsdtHeader->OEMID,
sizeof(DsdtHeader->OEMID)
);
strncpy(
oemTableID,
(PUCHAR) DsdtHeader->OEMTableID,
sizeof(DsdtHeader->OEMTableID)
);
strncpy(
creatorID,
(PUCHAR) DsdtHeader->CreatorID,
sizeof(DsdtHeader->CreatorID)
);
if (PrintFunction != NULL) {
PrintIndent( PrintFunction, IndentLevel );
PrintFunction(
"// CreatorID = %s\tCreatorRevision =%x.%x.%d\n",
creatorID,
DsdtHeader->CreatorRev >> 24,
( (DsdtHeader->CreatorRev >> 16) & 0xFF),
(DsdtHeader->CreatorRev & 0xFFFF)
);
PrintIndent( PrintFunction, IndentLevel );
PrintFunction(
"// TableLength = %d\tTableChkSum=0x%x\n\n",
DsdtHeader->Length,
DsdtHeader->Checksum
);
PrintIndent( PrintFunction, IndentLevel );
PrintFunction(
"DefinitionBlock(\"%s.AML\", \"%s\", 0x%02x, \"%s\", \"%s\", 0x%08x)",
signature,
signature,
DsdtHeader->Revision,
oemID,
oemTableID,
DsdtHeader->OEMRevision
);
}
return status;
}
NTSTATUS
EXPORT
UnAsmLoadDSDT(
PUCHAR DSDT
)
/*++
Routine Description:
This routine causes the unassmebler to initialize itself with the
given DSDT
Arguments:
DSDT - Where the DSDT is located in memory
PrintFunction - What function to call to print to the user
DsdtLocation - Where the DSDT is located in memory
IndentLevel - How much space to indent from the left margin
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDESCRIPTION_HEADER header = (PDESCRIPTION_HEADER) DSDT;
PUCHAR localDSDT;
ENTER( (1, "UnAsmLoadDSDT(%08lx)\n", DSDT) );
//
// Step 1: Create the root namespace
//
status = CreateNameSpaceObject( "\\", NULL, NULL, NULL, NSF_EXIST_ERR );
if (NT_SUCCESS(status)) {
static struct _defobj {
PUCHAR Name;
ULONG ObjectType;
} DefinedRootObjects[] = {
"_GPE", OBJTYPE_UNKNOWN,
"_PR", OBJTYPE_UNKNOWN,
"_SB", OBJTYPE_UNKNOWN,
"_SI", OBJTYPE_UNKNOWN,
"_TZ", OBJTYPE_UNKNOWN,
"_REV", OBJTYPE_INTDATA,
"_OS", OBJTYPE_STRDATA,
"_GL", OBJTYPE_MUTEX,
NULL, 0
};
ULONG i;
PNSOBJ nameObject;
CurrentScopeNameSpaceObject = RootNameSpaceObject;
for (i = 0; DefinedRootObjects[i].Name != NULL; i++) {
//
// Step 2: Create the fixed objects
//
status = CreateNameSpaceObject(
DefinedRootObjects[i].Name,
NULL,
NULL,
&nameObject,
NSF_EXIST_ERR
);
if (NT_SUCCESS(status)) {
nameObject->ObjectData.DataType =
DefinedRootObjects[i].ObjectType;
} else {
break;
}
}
if (NT_SUCCESS(status)) {
ASSERT(RootNameSpaceObject != NULL);
CurrentOwnerNameSpaceObject = NULL;
CurrentScopeNameSpaceObject = RootNameSpaceObject;
TopOpcode = CurrentOpcode = DSDT;
//
// Step 3: Dump the header
//
status = UnAsmHeader( header, NULL, 0, 0 );
if (NT_SUCCESS(status)) {
//
// Step 4: Dump the scope
//
localDSDT = DSDT + sizeof(DESCRIPTION_HEADER);
status = UnAsmScope(
&localDSDT,
(PUCHAR) (DSDT + header->Length),
NULL,
0,
0
);
}
}
}
if (NT_SUCCESS(status)) {
DSDTLoaded = 1;
}
EXIT( (1, "UnAsmLoadDSDT=%08lx\n", status ) );
return status;
}
NTSTATUS
LOCAL
UnAsmNameObj(
PUCHAR *OpCode,
PNSOBJ *NameObject,
UCHAR ObjectType,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble name object
Arguments:
OpCode - Pointer to the OpCode
NameObject - Where to store the NS object if one is found/created
ObjecType - Type of NS object
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
UCHAR name[MAX_NAME_LEN + 1];
ULONG length = 0;
name[0] = '\0';
if (**OpCode == OP_ROOT_PREFIX){
name[length] = '\\';
length++;
(*OpCode)++;
status = ParseNameTail(OpCode, name, length);
} else if (**OpCode == OP_PARENT_PREFIX) {
name[length] = '^';
length++;
(*OpCode)++;
while ((**OpCode == OP_PARENT_PREFIX) && (length < MAX_NAME_LEN)) {
name[length] = '^';
length++;
(*OpCode)++;
}
if (**OpCode == OP_PARENT_PREFIX) {
status = STATUS_OBJECT_NAME_INVALID;
} else {
status = ParseNameTail(OpCode, name, length);
}
} else {
status = ParseNameTail(OpCode, name, length);
}
if (NT_SUCCESS(status)) {
PNSOBJ localObject = NULL;
if (PrintFunction != NULL) {
PrintFunction("%s", name);
}
if (isupper(ObjectType) || (PrintFunction != NULL)) {
status = GetNameSpaceObject(
name,
CurrentScopeNameSpaceObject,
&localObject,
0
);
if (!NT_SUCCESS(status)) {
status = STATUS_SUCCESS;
}
} else {
status = CreateObject(
name,
(UCHAR) _toupper(ObjectType),
&localObject
);
}
if (NT_SUCCESS(status)) {
if ((ObjectType == NSTYPE_SCOPE) && (localObject != NULL)) {
CurrentScopeNameSpaceObject = localObject;
}
if (NameObject != NULL) {
*NameObject = localObject;
}
}
}
return status;
}
NTSTATUS
LOCAL
UnAsmOpcode(
PUCHAR *OpCode,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble an Opcode
Arguments:
OpCode - Pointer to the OpCode
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PASLTERM term;
PNSOBJ nameObject;
UCHAR opCodeClass;
UCHAR unAsmArgTypes[MAX_ARGS+1];
ULONG i;
ULONG localOpCode;
if (**OpCode == OP_EXT_PREFIX) {
(*OpCode)++;
localOpCode = ( ( (ULONG) **OpCode) << 8) | OP_EXT_PREFIX;
opCodeClass = FindOpClass(**OpCode, ExOpClassTable);
} else {
localOpCode = (ULONG)(**OpCode);
opCodeClass = OpClassTable[**OpCode];
}
switch (opCodeClass) {
case OPCLASS_DATA_OBJ:
status = UnAsmDataObj(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
break;
case OPCLASS_NAME_OBJ:
status = UnAsmNameObj(
OpCode,
&nameObject,
NSTYPE_UNKNOWN,
PrintFunction,
BaseAddress,
IndentLevel
);
if (NT_SUCCESS(status) && nameObject != NULL &&
nameObject->ObjectData.DataType == OBJTYPE_METHOD) {
for (i = 0; i < nameObject->ObjectData.DataValue; i++) {
unAsmArgTypes[i] = 'C';
}
unAsmArgTypes[i] = '\0';
status = UnAsmArgs(
unAsmArgTypes,
NULL,
OpCode,
NULL,
PrintFunction,
BaseAddress,
IndentLevel
);
}
break;
case OPCLASS_ARG_OBJ:
case OPCLASS_LOCAL_OBJ:
case OPCLASS_CODE_OBJ:
case OPCLASS_CONST_OBJ:
term = FindOpTerm( localOpCode );
if (term == NULL) {
status = STATUS_ACPI_INVALID_OPCODE;
} else {
(*OpCode)++;
status = UnAsmTermObj(
term,
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
}
break;
default:
status = STATUS_ACPI_INVALID_OPCODE;
}
return status;
}
NTSTATUS
LOCAL
UnAsmPkgList(
PUCHAR *OpCode,
PUCHAR OpCodeEnd,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble Package List
Arguments:
OpCode - Pointer to the OpCode
OpCodeEnd - End of List
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PASLTERM term;
//
// This is another place that DumpCode() was being called from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("{\n");
}
IndentLevel++;
while ((*OpCode < OpCodeEnd) && NT_SUCCESS(status)) {
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
}
if ((**OpCode == OP_BUFFER) ||
(**OpCode == OP_PACKAGE) ||
(OpClassTable[**OpCode] == OPCLASS_CONST_OBJ) ) {
term = FindOpTerm( (ULONG)(**OpCode) );
ASSERT(term != NULL);
(*OpCode)++;
status = UnAsmTermObj(
term,
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if (OpClassTable[**OpCode] == OPCLASS_NAME_OBJ) {
status = UnAsmNameObj(
OpCode,
NULL,
NSTYPE_UNKNOWN,
PrintFunction,
BaseAddress,
IndentLevel
);
} else {
status = UnAsmDataObj(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
}
if ((*OpCode < OpCodeEnd) && NT_SUCCESS(status) &&
(PrintFunction != NULL) ) {
PrintFunction(",");
}
//
// This is another place that DumpCode() was being called from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
}
IndentLevel--;
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("}");
}
return status;
}
NTSTATUS
LOCAL
UnAsmScope(
PUCHAR *OpCode,
PUCHAR OpCodeEnd,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
OpCode - Pointer to the current Opcode
OpCodeEnd - End of Scope
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
//
// Note: This is where DumpCode used to be called, so if this code
// is ever changed to dump the by bytes of the previous whatever, then
// this is where it needs to be done from
//
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
//
// Indent to the proper amount and dump opening brace
//
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("{\n");
}
//
// Increase the indent level for future recursion
//
IndentLevel++;
//
// Loop while there are bytes in the scope
//
while ((NT_SUCCESS(status)) && (*OpCode < OpCodeEnd)) {
//
// Indent Again
//
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
}
//
// Unassemble
//
status = UnAsmOpcode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
//
// This is another place where DumpCode was being called from
//
if ( StartOpcode != *OpCode) {
DumpCode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if (PrintFunction != NULL) {
PrintFunction("\n");
}
}
//
// Return the IndentLevel to its proper value
//
IndentLevel--;
//
// Print the trailing brace
//
if (PrintFunction != NULL) {
PrintIndent(PrintFunction, IndentLevel);
PrintFunction("}");
}
//
// Done
//
return status;
}
NTSTATUS
LOCAL
UnAsmSuperName(
PUCHAR *OpCode,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble supernames
Arguments:
OpCode - Pointer to the OpCode
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
if (**OpCode == 0) {
(*OpCode)++;
} else if ((**OpCode == OP_EXT_PREFIX) && (*(*OpCode + 1) == EXOP_DEBUG)) {
if (PrintFunction != NULL) {
PrintFunction("Debug");
}
*OpCode += 2;
} else if (OpClassTable[**OpCode] == OPCLASS_NAME_OBJ) {
status = UnAsmNameObj(
OpCode,
NULL,
NSTYPE_UNKNOWN,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if ((**OpCode == OP_INDEX) ||
(OpClassTable[**OpCode] == OPCLASS_ARG_OBJ) ||
(OpClassTable[**OpCode] == OPCLASS_LOCAL_OBJ)) {
status = UnAsmOpcode(
OpCode,
PrintFunction,
BaseAddress,
IndentLevel
);
} else {
status = STATUS_ACPI_INVALID_SUPERNAME;
}
return status;
}
NTSTATUS
LOCAL
UnAsmTermObj(
PASLTERM Term,
PUCHAR *OpCode,
PUNASM_PRINT PrintFunction,
ULONG_PTR BaseAddress,
ULONG IndentLevel
)
/*++
Routine Description:
Unassemble term object
Arguments:
Term - Term Table Entry
OpCode - Pointer to the OpCode
PrintFunction - Function to call to print information
BaseAddress - Where the start of the scope lies, in memory
IndentLevel - How much white space to leave on the left
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PNSOBJ scopeObject = CurrentScopeNameSpaceObject;
PNSOBJ nameObject = NULL;
PUCHAR opCodeEnd = NULL;
if (PrintFunction != NULL) {
PrintFunction("%s", Term->ID);
}
if (Term->Flags & TF_PACKAGE_LEN) {
ParsePackageLen(OpCode, &opCodeEnd);
}
if (Term->UnAsmArgTypes != NULL) {
status = UnAsmArgs(
Term->UnAsmArgTypes,
Term->ArgActions,
OpCode,
&nameObject,
PrintFunction,
BaseAddress,
IndentLevel
);
}
if (NT_SUCCESS(status)) {
if (Term->Flags & TF_DATA_LIST) {
status = UnAsmDataList(
OpCode,
opCodeEnd,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if (Term->Flags & TF_PACKAGE_LIST) {
status = UnAsmPkgList(
OpCode,
opCodeEnd,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if (Term->Flags & TF_FIELD_LIST) {
status = UnAsmFieldList(
OpCode,
opCodeEnd,
PrintFunction,
BaseAddress,
IndentLevel
);
} else if (Term->Flags & TF_PACKAGE_LEN) {
if (nameObject != NULL) {
CurrentScopeNameSpaceObject = nameObject;
}
status = UnAsmScope(
OpCode,
opCodeEnd,
PrintFunction,
BaseAddress,
IndentLevel
);
}
}
CurrentScopeNameSpaceObject = scopeObject;
return status;
}