/*++ 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; }