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