503 lines
11 KiB
C
503 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
acpi.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
WinDbg Extension Api for interpretting ACPI data structures
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Stephane Plante (splante) 21-Mar-1997
|
|||
|
|
|||
|
Based on Code by:
|
|||
|
Peter Wieland (peterwie) 16-Oct-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
UCHAR BuildBuffer[2048];
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
dumpAcpiBuildListHeader(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine displays the top line in the build list dump
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
dprintf("Request Wd Cu Nx BuildCon NsObj Status Union Special\n");
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
dumpAcpiBuildList(
|
|||
|
IN PUCHAR ListName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
This routine fetects a single Power Device List from the target and
|
|||
|
displays it
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL status;
|
|||
|
LIST_ENTRY listEntry;
|
|||
|
ULONG_PTR address;
|
|||
|
ULONG returnLength;
|
|||
|
|
|||
|
//
|
|||
|
// Handle the queue list
|
|||
|
//
|
|||
|
address = GetExpression( ListName );
|
|||
|
if (!address) {
|
|||
|
|
|||
|
dprintf( "dumpAcpiBuildList: could not read %s\n", ListName );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf("%s at %08lx\n", ListName, address );
|
|||
|
status = ReadMemory(
|
|||
|
address,
|
|||
|
&listEntry,
|
|||
|
sizeof(LIST_ENTRY),
|
|||
|
&returnLength
|
|||
|
);
|
|||
|
if (status == FALSE || returnLength != sizeof(LIST_ENTRY)) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"dumpAcpiBuildList: could not read LIST_ENTRY at %p\n",
|
|||
|
address
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dumpAcpiBuildListHeader();
|
|||
|
dumpBuildDeviceListEntry(
|
|||
|
&listEntry,
|
|||
|
address,
|
|||
|
0
|
|||
|
);
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
dumpAcpiBuildLists(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine dumps all of the devices lists used by the Build DPC
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL status;
|
|||
|
LIST_ENTRY listEntry;
|
|||
|
ULONG_PTR address;
|
|||
|
ULONG returnLength;
|
|||
|
ULONG value;
|
|||
|
|
|||
|
status = GetUlongPtr( "ACPI!AcpiDeviceTreeLock", &address );
|
|||
|
if (status == FALSE) {
|
|||
|
|
|||
|
dprintf("dumpAcpiBuildLists: Could not read ACPI!AcpiDeviceTreeLock\n");
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
dprintf("ACPI Build Tree Information\n");
|
|||
|
if (address) {
|
|||
|
|
|||
|
dprintf(" + ACPI!AcpiDeviceTreeLock is owned");
|
|||
|
|
|||
|
//
|
|||
|
// The bits other then the lowest is where the owning thread is
|
|||
|
// located. This function uses the property that -2 is every bit
|
|||
|
// except the least significant one
|
|||
|
//
|
|||
|
if ( (address & (ULONG_PTR) -2) != 0) {
|
|||
|
|
|||
|
dprintf(" by thread at %p\n", (address & (ULONG_PTR) - 2) );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf(" - ACPI!AcpiDeviceTreeLock is not owned\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
status = GetUlongPtr( "ACPI!AcpiBuildQueueLock", &address );
|
|||
|
if (status == FALSE) {
|
|||
|
|
|||
|
dprintf("dumpAcpiBuildLists: Could not read ACPI!AcpiBuildQueueLock\n");
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
if (address) {
|
|||
|
|
|||
|
dprintf(" + ACPI!AcpiBuildQueueLock is owned\n");
|
|||
|
|
|||
|
if ( (address & (ULONG_PTR) -2) != 0) {
|
|||
|
|
|||
|
dprintf(" by thread at %p\n", (address & (ULONG_PTR) - 2) );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf(" - ACPI!AcpiBuildQueueLock is not owned\n" );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
status = GetUlong( "ACPI!AcpiBuildWorkDone", &value );
|
|||
|
if (status == FALSE) {
|
|||
|
|
|||
|
dprintf("dumpAcpiBuildLists: Could not read ACPI!AcpiBuildWorkDone\n");
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
dprintf(" + AcpiBuildWorkDone = %s\n", (value ? "TRUE" : "FALSE" ) );
|
|||
|
|
|||
|
|
|||
|
status = GetUlong( "ACPI!AcpiBuildDpcRunning", &value );
|
|||
|
if (status == FALSE) {
|
|||
|
|
|||
|
dprintf("dumpAcpiBuildLists: Could not read ACPI!AcpiBuildDpcRunning\n");
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
dprintf(" + AcpiBuildDpcRunning = %s\n", (value ? "TRUE" : "FALSE" ) );
|
|||
|
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildQueueList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildDeviceList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildOperationRegionList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildPowerResourceList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildRunMethodList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildSynchronizationList" );
|
|||
|
dumpAcpiBuildList( "ACPI!AcpiBuildThermalZoneList" );
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
dumpBuildDeviceListEntry(
|
|||
|
IN PLIST_ENTRY ListEntry,
|
|||
|
IN ULONG_PTR Address,
|
|||
|
IN ULONG Verbose
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to dump a list of devices in one of the queues
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ListEntry - The head of the list
|
|||
|
Address - The original address of the list (to see when we looped
|
|||
|
around
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NONE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG_PTR displacement;
|
|||
|
ACPI_BUILD_REQUEST request;
|
|||
|
BOOL stat;
|
|||
|
PACPI_BUILD_REQUEST requestAddress;
|
|||
|
UCHAR buffer1[80];
|
|||
|
UCHAR buffer2[80];
|
|||
|
UCHAR buffer3[5];
|
|||
|
ULONG i = 0;
|
|||
|
ULONG returnLength;
|
|||
|
|
|||
|
memset( buffer3, 0, 5);
|
|||
|
memset( buffer2, 0, 80);
|
|||
|
memset( buffer1, 0, 80);
|
|||
|
|
|||
|
//
|
|||
|
// Look at the next address
|
|||
|
//
|
|||
|
ListEntry = ListEntry->Flink;
|
|||
|
|
|||
|
while (ListEntry != (PLIST_ENTRY) Address) {
|
|||
|
|
|||
|
//
|
|||
|
// Crack the listEntry to determine where the powerRequest is
|
|||
|
//
|
|||
|
requestAddress = CONTAINING_RECORD(
|
|||
|
ListEntry,
|
|||
|
ACPI_BUILD_REQUEST,
|
|||
|
ListEntry
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Read the queued item
|
|||
|
//
|
|||
|
stat = ReadMemory(
|
|||
|
(ULONG_PTR) requestAddress,
|
|||
|
&request,
|
|||
|
sizeof(ACPI_BUILD_REQUEST),
|
|||
|
&returnLength
|
|||
|
);
|
|||
|
if (stat == FALSE || returnLength != sizeof(ACPI_BUILD_REQUEST)) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"dumpBuildDeviceListEntry: Cannot read BuildRequest at %08lx\n",
|
|||
|
requestAddress
|
|||
|
);
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (request.CallBack != NULL) {
|
|||
|
|
|||
|
GetSymbol(
|
|||
|
request.CallBack,
|
|||
|
buffer1,
|
|||
|
&displacement
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
buffer1[0] = '\0';
|
|||
|
|
|||
|
}
|
|||
|
if (request.Flags & BUILD_REQUEST_VALID_TARGET) {
|
|||
|
|
|||
|
GetSymbol(
|
|||
|
request.TargetListEntry,
|
|||
|
buffer2,
|
|||
|
&displacement
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
buffer2[0] = '\0';
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the entry for the device
|
|||
|
//
|
|||
|
if (!Verbose) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"%08lx %2x %2x %2x %08lx %08lx %08lx %08lx",
|
|||
|
requestAddress,
|
|||
|
request.WorkDone,
|
|||
|
request.CurrentWorkDone,
|
|||
|
request.NextWorkDone,
|
|||
|
request.BuildContext,
|
|||
|
request.CurrentObject,
|
|||
|
request.Status,
|
|||
|
request.String
|
|||
|
);
|
|||
|
if (request.Flags & BUILD_REQUEST_VALID_TARGET) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" T: %08lx (%s)",
|
|||
|
request.TargetListEntry,
|
|||
|
buffer2
|
|||
|
);
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_DEVICE) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" O: %08lx",
|
|||
|
requestAddress + FIELD_OFFSET( ACPI_BUILD_REQUEST, DeviceRequest.ResultData )
|
|||
|
);
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_RUN) {
|
|||
|
|
|||
|
memcpy( buffer3, request.RunRequest.ControlMethodNameAsUchar, 4);
|
|||
|
dprintf(
|
|||
|
" R: %4s",
|
|||
|
buffer3
|
|||
|
);
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_CHECK_STATUS) {
|
|||
|
|
|||
|
dprintf(" Sta");
|
|||
|
|
|||
|
}
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_MARK_INI) {
|
|||
|
|
|||
|
dprintf(" Ini");
|
|||
|
|
|||
|
}
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_RECURSIVE) {
|
|||
|
|
|||
|
dprintf(" Rec");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_SYNC) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" S: %08lx",
|
|||
|
request.SynchronizeRequest.SynchronizeListEntry
|
|||
|
);
|
|||
|
if (request.SynchronizeRequest.Flags & SYNC_REQUEST_HAS_METHOD) {
|
|||
|
|
|||
|
memcpy( buffer3, request.SynchronizeRequest.SynchronizeMethodNameAsUchar, 4);
|
|||
|
dprintf(
|
|||
|
" %4s",
|
|||
|
buffer3
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (request.CallBack != NULL) {
|
|||
|
|
|||
|
dprintf(" C: %s(%08lx)", buffer1, request.CallBackContext);
|
|||
|
|
|||
|
}
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"%08lx\n"
|
|||
|
" BuildContext: %08lx\n"
|
|||
|
" ListEntry: F - %08lx B - %08lx\n"
|
|||
|
" CallBack: %08lx (%s)\n"
|
|||
|
" CallBackContext: %08lx\n"
|
|||
|
" WorkDone: %lx\n"
|
|||
|
" CurrentWorkDone: %lx\n"
|
|||
|
" NextWorkDone: %lx\n"
|
|||
|
" CurrentObject: %08lx\n"
|
|||
|
" Status: %08lx\n"
|
|||
|
" Flags: %08lx\n"
|
|||
|
" Spare: %08lx\n",
|
|||
|
requestAddress,
|
|||
|
request.BuildContext,
|
|||
|
request.ListEntry.Flink,
|
|||
|
request.ListEntry.Blink,
|
|||
|
request.CallBack,
|
|||
|
buffer1,
|
|||
|
request.CallBackContext,
|
|||
|
request.WorkDone,
|
|||
|
request.CurrentWorkDone,
|
|||
|
request.NextWorkDone,
|
|||
|
request.CurrentObject,
|
|||
|
request.Status,
|
|||
|
request.Flags,
|
|||
|
request.String
|
|||
|
);
|
|||
|
if (request.Flags & BUILD_REQUEST_VALID_TARGET) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" TargetListEntry: %08lx (%s)\n",
|
|||
|
request.TargetListEntry,
|
|||
|
buffer2
|
|||
|
);
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_DEVICE) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" ResultData: %08lx\n",
|
|||
|
requestAddress + FIELD_OFFSET( ACPI_BUILD_REQUEST, DeviceRequest.ResultData )
|
|||
|
);
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_RUN) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" ControlMethodName: %4s\n"
|
|||
|
" ControlMethodFlags: %08lx",
|
|||
|
request.RunRequest.ControlMethodName
|
|||
|
);
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_CHECK_STATUS) {
|
|||
|
|
|||
|
dprintf(" Sta");
|
|||
|
|
|||
|
}
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_MARK_INI) {
|
|||
|
|
|||
|
dprintf(" Ini");
|
|||
|
|
|||
|
}
|
|||
|
if (request.RunRequest.Flags & RUN_REQUEST_RECURSIVE) {
|
|||
|
|
|||
|
dprintf(" Rec");
|
|||
|
|
|||
|
}
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
} else if (request.Flags & BUILD_REQUEST_SYNC) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
" SynchronizeListEntry: %08lx\n"
|
|||
|
" MethodName: %4s\n",
|
|||
|
request.SynchronizeRequest.SynchronizeListEntry,
|
|||
|
request.SynchronizeRequest.SynchronizeMethodNameAsUchar
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
dprintf("\n");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Point to the next entry
|
|||
|
//
|
|||
|
ListEntry = request.ListEntry.Flink;
|
|||
|
|
|||
|
} // while
|
|||
|
|
|||
|
}
|
|||
|
|