You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2005 lines
40 KiB
2005 lines
40 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|