/*++ 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" extern FILE *outputFile; BOOL ReadPhysicalOrVirtual( IN ULONG_PTR Address, IN PVOID Buffer, IN ULONG Size, IN OUT PULONG ReturnLength, IN BOOL Virtual ) /*++ Routine Description: This is a way to abstract out the differences between ROM images and mapped memory Arguments: Address - Where (either physical, or virtual) the buffer is located Buffer - Address of where to copy the memory to Size - How many bytes to copy (maximum) ReturnLength - How many bytes where copied Virtual - False if this is physical memory --*/ { BOOL status = TRUE; PHYSICAL_ADDRESS physicalAddress = { 0L, 0L }; if (Virtual) { status = ReadMemory( Address, Buffer, Size, ReturnLength ); } else { physicalAddress.QuadPart = Address; ReadPhysical( physicalAddress.QuadPart, Buffer, Size, ReturnLength ); } if (ReturnLength && *ReturnLength != Size) { // // Didn't get enough memory // status = FALSE; } return status; } VOID dumpAcpiGpeInformation( VOID ) { ACPIInformation acpiInformation; BOOL status; UCHAR gpeEnable[MAX_GPE_BUFFER_SIZE]; UCHAR gpeCurEnable[MAX_GPE_BUFFER_SIZE]; UCHAR gpeWakeEnable[MAX_GPE_BUFFER_SIZE]; UCHAR gpeIsLevel[MAX_GPE_BUFFER_SIZE]; UCHAR gpeHandlerType[MAX_GPE_BUFFER_SIZE]; UCHAR gpeWakeHandler[MAX_GPE_BUFFER_SIZE]; UCHAR gpeSpecialHandler[MAX_GPE_BUFFER_SIZE]; UCHAR gpePending[MAX_GPE_BUFFER_SIZE]; UCHAR gpeMap[MAX_GPE_BUFFER_SIZE * 8]; UCHAR gpeRunMethod[MAX_GPE_BUFFER_SIZE]; UCHAR gpeComplete[MAX_GPE_BUFFER_SIZE]; ULONG_PTR address; ULONG acpiGpeRunning; ULONG acpiGpeWorkDone; ULONG returnLength; ULONG size; ULONG value = 0; ULONG i; // // Get the ACPI Information Table // status = GetUlongPtr("ACPI!AcpiInformation", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!AcpiInformation\n"); return; } status = ReadMemory( address, &acpiInformation, sizeof(ACPIInformation), &returnLength ); if (!status || returnLength != sizeof(ACPIInformation)) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", sizeof(ACPIInformation), address ); return; } // // Read the current masks from the OS // status = GetUlongPtr("ACPI!GpeEnable", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeEnable\n"); return; } status = ReadMemory( address, gpeEnable, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeCurEnable", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeCurEnable\n"); return; } status = ReadMemory( address, gpeCurEnable, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeWakeEnable", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeWakeEnable\n"); return; } status = ReadMemory( address, gpeWakeEnable, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeIsLevel", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeIsLevel\n"); return; } status = ReadMemory( address, gpeIsLevel, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeHandlerType", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeHandlerType\n"); return; } status = ReadMemory( address, gpeHandlerType, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeWakeHandler", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeWakeHandler\n"); return; } status = ReadMemory( address, gpeWakeHandler, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeSpecialHandler", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeSpecialHandler\n"); return; } status = ReadMemory( address, gpeSpecialHandler, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpePending", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpePending\n"); return; } status = ReadMemory( address, gpePending, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeRunMethod", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpePending\n"); return; } status = ReadMemory( address, gpeRunMethod, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeComplete", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpePending\n"); return; } status = ReadMemory( address, gpeComplete, acpiInformation.GpeSize, &returnLength ); if (!status || returnLength != acpiInformation.GpeSize) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", acpiInformation.GpeSize, address ); return; } status = GetUlongPtr("ACPI!GpeMap", &address); if (!status) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!GpeMap\n"); return; } status = ReadMemory( address, gpeMap, (acpiInformation.GpeSize * 8), &returnLength ); if (!status || returnLength != (ULONG) (acpiInformation.GpeSize * 8) ) { dprintf( "dumpAcpiGpeInformation: Could not read %x bytes at %x\n", (acpiInformation.GpeSize * 8), address ); return; } status = GetUlong( "ACPI!AcpiGpeDpcRunning", &acpiGpeRunning ); if (status == FALSE) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!AcpiGpeDpcRunning\n"); return; } status = GetUlong( "ACPI!AcpiGpeWorkDone", &acpiGpeWorkDone ); if (status == FALSE) { dprintf("dumpAcpiGpeInformation: Could not read ACPI!AcpiGpeDpcRunning\n"); return; } dprintf("ACPI General Purpose Events\n"); dprintf(" + AcpiGpeDpcRunning = %s\n", (acpiGpeRunning ? "TRUE" : "FALSE" ) ); dprintf(" + AcpiGpeWorkDone = %s\n", (acpiGpeRunning ? "TRUE" : "FALSE" ) ); dprintf( " Register Size: %d bytes\n", (acpiInformation.Gpe0Size + acpiInformation.Gpe1Size) ); dprintf(" Status Register: "); for (i = acpiInformation.Gpe1Size; i > 0; i--) { size = 1; ReadIoSpace( (ULONG) acpiInformation.GP1_BLK + (i - 1), &value, &size ); if (!size) { } dprintf(" %02x", value ); } for (i = acpiInformation.Gpe0Size; i > 0; i--) { size = 1; ReadIoSpace( (ULONG) acpiInformation.GP0_BLK + (i - 1), &value, &size ); if (!size) { value = 0; } dprintf(" %02x", value ); } dprintf("\n"); dprintf(" Enable Register: "); for (i = acpiInformation.Gpe1Size; i > 0; i--) { size = 1; ReadIoSpace( (ULONG) acpiInformation.GP1_ENABLE + (i - 1), &value, &size ); if (!size) { value = 0; } dprintf(" %02x", value ); } for (i = acpiInformation.Gpe0Size; i > 0; i--) { size = 1; ReadIoSpace( (ULONG) acpiInformation.GP0_ENABLE + (i - 1), &value, &size ); if (!size) { value = 0; } dprintf(" %02x", value ); } dprintf("\n"); dprintf(" OS Enable Mask: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeEnable[i-1] ); } dprintf("\n"); dprintf(" OS Current Mask: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeCurEnable[i-1] ); } dprintf("\n"); dprintf(" OS Wake Mask: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeWakeEnable[i-1] ); } dprintf("\n"); dprintf(" GPE Level Type: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeIsLevel[i-1] ); } dprintf("\n"); dprintf(" GPE Handler Type: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeHandlerType[i-1] ); } dprintf("\n"); dprintf(" GPE Wake Handler: "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeWakeHandler[i-1] ); } dprintf("\n"); dprintf(" Special GPEs : "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeSpecialHandler[i-1] ); } dprintf("\n"); dprintf(" Pending GPEs : "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpePending[i-1] ); } dprintf("\n"); dprintf(" RunMethod GPEs : "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeRunMethod[i-1] ); } dprintf("\n"); dprintf(" Complete GPEs : "); for (i = acpiInformation.GpeSize; i > 0; i--) { dprintf(" %02x", gpeComplete[i-1] ); } dprintf("\n"); dprintf(" GPE Map : "); for (i = 0 ; i < (ULONG) (acpiInformation.GpeSize * 8); i++) { dprintf(" %02x", gpeMap[i]); if ( ((i+1) % 16) == 0) { dprintf("\n "); } } dprintf("\n"); } VOID dumpAcpiInformation( VOID ) { BOOL status; ACPIInformation acpiInformation; ULONG_PTR address; ULONG returnLength; ULONG size; ULONG value; ULONG i; status = GetUlongPtr( "ACPI!AcpiInformation", &address ); if (status == FALSE) { dprintf("dumpAcpiInformation: Could not read ACPI!AcpiInformation\n"); return; } status = ReadMemory( address, &acpiInformation, sizeof(ACPIInformation), &returnLength ); if (!status || returnLength != sizeof(ACPIInformation)) { dprintf( "dumpAcpiInformation: Could not read %x bytes at %x\n", sizeof(ACPIInformation), address ); return; } dprintf("ACPIInformation (%08lx)\n", address); dprintf( " RSDT - %x\n", acpiInformation.RootSystemDescTable ); dprintf( " FADT - %x\n", acpiInformation.FixedACPIDescTable ); dprintf( " FACS - %x\n", acpiInformation.FirmwareACPIControlStructure ); dprintf( " DSDT - %x\n", acpiInformation.DiffSystemDescTable ); dprintf( " GlobalLock - %x\n", acpiInformation.GlobalLock ); dprintf( " GlobalLockQueue - F - %x B - %x\n", acpiInformation.GlobalLockQueue.Flink, acpiInformation.GlobalLockQueue.Blink ); dprintf( " GlobalLockQueueLock - %x\n", acpiInformation.GlobalLockQueueLock ); dprintf( " GlobalLockOwnerContext - %x\n", acpiInformation.GlobalLockOwnerContext ); dprintf( " GlobalLockOwnerDepth - %x\n", acpiInformation.GlobalLockOwnerDepth ); dprintf( " ACPIOnly - %s\n", (acpiInformation.ACPIOnly ? "TRUE" : "FALSE" ) ); dprintf( " PM1a_BLK - %x", acpiInformation.PM1a_BLK ); if (acpiInformation.PM1a_BLK) { size = 4; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM1a_BLK, &value, &size ); if (size) { dprintf(" (%04x) (%04x)\n", (value & 0xFFFF), (value >> 16) ); dumpPM1StatusRegister( value, 5 ); } else { dprintf(" (N/A)\n" ); } } else { dprintf(" (N/A)\n"); } dprintf( " PM1b_BLK - %x", acpiInformation.PM1b_BLK ); if (acpiInformation.PM1b_BLK) { size = 4; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM1b_BLK, &value, &size ); if (size) { dprintf(" (%04x) (%04x)\n", (value & 0xFFFF), (value >> 16) ); dumpPM1StatusRegister( value, 5 ); } else { dprintf(" (N/A)\n" ); } } else { dprintf(" (N/A)\n" ); } dprintf( " PM1a_CTRL_BLK - %x", acpiInformation.PM1a_CTRL_BLK ); if (acpiInformation.PM1a_CTRL_BLK) { size = 2; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM1a_CTRL_BLK, &value, &size ); if (size) { dprintf(" (%04x)\n", (value & 0xFFFF) ); dumpPM1ControlRegister( value, 5 ); } else { dprintf(" (N/A)\n" ); } } else { dprintf(" (N/A)\n" ); } dprintf( " PM1b_CTRL_BLK - %x", acpiInformation.PM1b_CTRL_BLK ); if (acpiInformation.PM1b_CTRL_BLK) { size = 2; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM1b_CTRL_BLK, &value, &size ); if (size) { dprintf(" (%04x)\n", (value & 0xFFFF)); dumpPM1ControlRegister( value, 5 ); } else { dprintf(" (N/A)\n" ); } } else { dprintf(" (N/A)\n" ); } dprintf( " PM2_CTRL_BLK - %x", acpiInformation.PM2_CTRL_BLK ); if (acpiInformation.PM2_CTRL_BLK) { size = 1; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM2_CTRL_BLK, &value, &size ); if (size) { dprintf(" (%02x)\n", (value & 0xFF) ); if (value & 0x1) { dprintf(" 0 - ARB_DIS\n"); } } else { dprintf(" (N/A)\n"); } } else { dprintf(" (N/A)\n"); } dprintf( " PM_TMR - %x", acpiInformation.PM_TMR ); if (acpiInformation.PM_TMR) { size = 4; value = 0; ReadIoSpace( (ULONG) acpiInformation.PM_TMR, &value, &size ); if (size) { dprintf(" (%08lx)\n", value ); } else { dprintf(" (N/A)\n"); } } else { dprintf(" (N/A)\n"); } dprintf( " GP0_BLK - %x", acpiInformation.GP0_BLK ); if (acpiInformation.GP0_BLK) { for(i = 0; i < acpiInformation.Gpe0Size; i++) { size = 1; value = 0; ReadIoSpace( (ULONG) acpiInformation.GP0_BLK + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP0_ENABLE - %x", acpiInformation.GP0_ENABLE ); if (acpiInformation.GP0_ENABLE) { for(i = 0; i < acpiInformation.Gpe0Size; i++) { size = 1; value = 0; ReadIoSpace( (ULONG) acpiInformation.GP0_ENABLE + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP0_LEN - %x\n", acpiInformation.GP0_LEN ); dprintf( " GP0_SIZE - %x\n", acpiInformation.Gpe0Size ); dprintf( " GP1_BLK - %x", acpiInformation.GP1_BLK ); if (acpiInformation.GP1_BLK) { for(i = 0; i < acpiInformation.Gpe0Size; i++) { size = 1; value = 0; ReadIoSpace( (ULONG) acpiInformation.GP1_BLK + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP1_ENABLE - %x", acpiInformation.GP1_ENABLE ); if (acpiInformation.GP1_ENABLE) { for(i = 0; i < acpiInformation.Gpe0Size; i++) { size = 1; value = 0; ReadIoSpace( (ULONG) acpiInformation.GP1_ENABLE + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP1_LEN - %x\n", acpiInformation.GP1_LEN ); dprintf( " GP1_SIZE - %x\n", acpiInformation.Gpe1Size ); dprintf( " GP1_BASE_INDEX - %x\n", acpiInformation.GP1_Base_Index ); dprintf( " GPE_SIZE - %x\n", acpiInformation.GpeSize ); dprintf( " PM1_EN_BITS - %04x\n", acpiInformation.pm1_en_bits ); dumpPM1StatusRegister( ( (ULONG) acpiInformation.pm1_en_bits << 16), 5 ); dprintf( " PM1_WAKE_MASK - %04x\n", acpiInformation.pm1_wake_mask ); dumpPM1StatusRegister( ( (ULONG) acpiInformation.pm1_wake_mask << 16), 5 ); dprintf( " C2_LATENCY - %x\n", acpiInformation.c2_latency ); dprintf( " C3_LATENCY - %x\n", acpiInformation.c3_latency ); dprintf( " ACPI_FLAGS - %x\n", acpiInformation.ACPI_Flags ); if (acpiInformation.ACPI_Flags & C2_SUPPORTED) { dprintf(" %2d - C2_SUPPORTED\n", C2_SUPPORTED_BIT); } if (acpiInformation.ACPI_Flags & C3_SUPPORTED) { dprintf(" %2d - C3_SUPPORTED\n", C3_SUPPORTED_BIT); } if (acpiInformation.ACPI_Flags & C3_PREFERRED) { dprintf(" %2d - C3_PREFERRED\n", C3_PREFERRED_BIT); } dprintf( " ACPI_CAPABILITIES - %x\n", acpiInformation.ACPI_Capabilities ); if (acpiInformation.ACPI_Capabilities & CSTATE_C1) { dprintf(" %2d - CSTATE_C1\n", CSTATE_C1_BIT ); } if (acpiInformation.ACPI_Capabilities & CSTATE_C2) { dprintf(" %2d - CSTATE_C2\n", CSTATE_C2_BIT ); } if (acpiInformation.ACPI_Capabilities & CSTATE_C3) { dprintf(" %2d - CSTATE_C3\n", CSTATE_C3_BIT ); } } #if 0 VOID dumpDSDT( IN ULONG_PTR Address, IN PUCHAR Name ) /*++ Routine Description: This dumps the DSDT at the specified address Arguments: The address where the DSDT is located at Return Value: None --*/ { BOOL status; BOOL virtualMemory; DESCRIPTION_HEADER dsdtHeader; NTSTATUS result; PDSDT dsdt; ULONG returnLength; ULONG index; // // Determine if we have virtual or physical memory // for (index = 0; index < 2; index++) { status = ReadPhysicalOrVirtual( Address, &dsdtHeader, sizeof(DESCRIPTION_HEADER), &returnLength, (BOOL) index ); if (!status) { continue; } else if (dsdtHeader.Signature != DSDT_SIGNATURE && dsdtHeader.Signature != SSDT_SIGNATURE && dsdtHeader.Signature != PSDT_SIGNATURE ) { continue; } else { break; } } // // This will set the policy for the rest of the operation // switch (index) { case 0: virtualMemory = FALSE; break; case 1: virtualMemory = TRUE; break; default: if (!status) { dprintf( "dumpDSDT: Could only read 0x%08lx of 0x%08lx bytes\n", returnLength, sizeof(DESCRIPTION_HEADER) ); } else { dprintf( "dumpDSDT: Unknown Signature 0x%08lx\n", dsdtHeader.Signature ); dumpHeader( Address, &dsdtHeader, TRUE ); } return; } // switch // // Do we have a correctly sized data structure // dsdt = LocalAlloc( LPTR, dsdtHeader.Length ); if (dsdt == NULL) { dprintf( "dumpDSDT: Could not allocate %#08lx bytes\n", Address, dsdtHeader.Length ); dumpHeader( Address, &dsdtHeader, TRUE ); return; } // // Read the data // status = ReadPhysicalOrVirtual( Address, dsdt, dsdtHeader.Length, &returnLength, virtualMemory ); if (!status) { dprintf( "dumpDSDT: Read %#08lx of %#08lx bytes\n", Address, returnLength, dsdtHeader.Length ); dumpHeader( Address, &dsdtHeader, TRUE ); LocalFree( dsdt ); return; } else if (dsdt->Header.Signature != DSDT_SIGNATURE && dsdt->Header.Signature != SSDT_SIGNATURE && dsdt->Header.Signature != PSDT_SIGNATURE) { dprintf( "dumpDSDT: Unkown Signature (%#08lx)\n", dsdt->Header.Signature ); dumpHeader( Address, &dsdtHeader, TRUE ); LocalFree( dsdt ); return; } // // Load the DSDT into the unassembler // if (!IsDSDTLoaded()) { result = UnAsmLoadDSDT( (PUCHAR) dsdt ); if (!NT_SUCCESS(result)) { dprintf( "dumpDSDT: Could not load DSDT %08lx because %08lx\n", dsdt, result ); return; } result = UnAsmLoadXSDTEx(); if (!NT_SUCCESS(result)) { dprintf( "dumpDSDT: Could not load XSDTs because %08lx\n", result ); return; } } if (Name == NULL) { result = UnAsmDSDT( (PUCHAR) dsdt, DisplayPrint, Address, 0 ); } else { outputFile = fopen( Name, "w"); if (outputFile == NULL) { dprintf("dumpDSDT: Could not open file \"%s\"\n", Name ); } else { result = UnAsmDSDT( (PUCHAR) dsdt, FilePrint, Address, 0 ); fflush( outputFile ); fclose( outputFile ); } } if (!NT_SUCCESS(result)) { dprintf("dumpDSDT: Unasm Error 0x%08lx\n", result ); } LocalFree( dsdt ); return; } #endif VOID dumpFACS( IN ULONG_PTR Address ) /*++ Routine Description: This dumps the FADT at the specified address Arguments: The address where the FADT is located at Return Value: NONE --*/ { BOOL status; FACS facs; ULONG index; ULONG returnLength; // // Read the data // dprintf("FACS - %#08lx\n", Address); for (index = 0; index < 2; index++) { status = ReadPhysicalOrVirtual( Address, &facs, sizeof(FACS), &returnLength, (BOOL) index ); if (!status || facs.Signature != FACS_SIGNATURE) { continue; } else { break; } } // // This will set the policy for the rest of the operation // switch (index) { default: break; case 2: if (!status) { dprintf( "dumpFACS: Could only read 0x%08lx of 0x%08lx bytes\n", returnLength, sizeof(FACS) ); } else { dprintf( "dumpFACS: Invalid Signature 0x%08lx != FACS_SIGNATURE\n", facs.Signature ); } return; } // switch // // Dump the table // memset( Buffer, 0, 2048 ); memcpy( Buffer, &(facs.Signature), sizeof(ULONG) ); dprintf( " Signature: %s\n" " Length: %#08lx\n" " Hardware Signature: %#08lx\n" " Firmware Wake Vector: %#08lx\n" " Global Lock : %#08lx\n", Buffer, facs.Length, facs.HardwareSignature, facs.pFirmwareWakingVector, facs.GlobalLock ); if ( (facs.GlobalLock & GL_PENDING) ) { dprintf(" Request for Ownership Pending\n"); } if ( (facs.GlobalLock & GL_OWNER) ) { dprintf(" Global Lock is Owned\n"); } dprintf(" Flags: %#08lx\n", facs.Flags ); if ( (facs.Flags & FACS_S4BIOS_SUPPORTED) ) { dprintf(" S4BIOS_REQ Supported\n"); } return; } VOID dumpFADT( IN ULONG_PTR Address ) /*++ Routine Description: This dumps the FADT at the specified address Arguments: The address where the FADT is located at Return Value: NONE --*/ { BOOL status; BOOL virtualMemory; DESCRIPTION_HEADER fadtHeader; FADT fadt; ULONG fadtLength; ULONG returnLength; ULONG index; PCHAR addressSpace; // // First check to see if we find the correct things // dprintf("FADT - "); for (index = 0; index < 2; index++) { status = ReadPhysicalOrVirtual( Address, &fadtHeader, sizeof(DESCRIPTION_HEADER), &returnLength, (BOOL) index ); if (!status || fadtHeader.Signature != FADT_SIGNATURE) { continue; } else { break; } } // // This will set the policy for the rest of the operation // switch (index) { case 0: virtualMemory = FALSE; break; case 1: virtualMemory = TRUE; break; default: if (!status) { dprintf( "dumpFADT: Could only read 0x%08lx of 0x%08lx bytes\n", returnLength, sizeof(DESCRIPTION_HEADER) ); } else { dprintf( "dumpFADT: Invalid Signature 0x%08lx != FADT_SIGNATURE\n", fadtHeader.Signature ); dumpHeader( Address, &fadtHeader, TRUE ); } return; } // switch if (fadtHeader.Revision == 1) { fadtLength = FADT_REV_1_SIZE; // 116 } else if (fadtHeader.Revision == 2) { fadtLength = FADT_REV_2_SIZE; // 129 } else { fadtLength = sizeof(FADT); } // // Do we have a correctly sized data structure // if (fadtHeader.Length < fadtLength) { dprintf( "dumpFADT: Length (%#08lx) is not the size of the FADT (%#08lx)\n", Address, fadtHeader.Length, fadtLength ); dumpHeader( Address, &fadtHeader, TRUE ); return; } // // Read the data // status = ReadPhysicalOrVirtual( Address, &fadt, fadtLength, &returnLength, virtualMemory ); if (!status) { dprintf( "dumpFADT: Read %#08lx of %#08lx bytes\n", Address, returnLength, sizeof(FADT) ); dumpHeader( Address, &fadtHeader, TRUE ); return; } else if (fadt.Header.Signature != FADT_SIGNATURE) { dprintf( "%#08lx: Signature (%#08lx) != fadt_SIGNATURE (%#08lx)\n", Address, fadt.Header.Signature, FADT_SIGNATURE ); dumpHeader( Address, &fadtHeader, TRUE ); return; } // // Dump the table // dumpHeader( Address, &(fadt.Header), TRUE ); dprintf( "FADT - BODY - %#08lx\n" " FACS: 0x%08lx\n" " DSDT: 0x%08lx\n" " Int Model: %s\n" " SCI Vector: 0x%03x\n" " SMI Port: 0x%08lx\n" " ACPI On Value: 0x%03x\n" " ACPI Off Value: 0x%03x\n" " SMI CMD For S4 State: 0x%03x\n" " PM1A Event Block: 0x%08lx\n" " PM1B Event Block: 0x%08lx\n" " PM1 Event Length: 0x%03x\n" " PM1A Control Block: 0x%08lx\n" " PM1B Control Block: 0x%08lx\n" " PM1 Control Length: 0x%03x\n" " PM2 Control Block: 0x%08lx\n" " PM2 Control Length: 0x%03x\n" " PM Timer Block: 0x%08lx\n" " PM Timer Length: 0x%03x\n" " GP0 Block: 0x%08lx\n" " GP0 Length: 0x%03x\n" " GP1 Block: 0x%08lx\n" " GP1 Length: 0x%08lx\n" " GP1 Base: 0x%08lx\n" " C2 Latency: 0x%05lx\n" " C3 Latency: 0x%05lx\n" " Memory Flush Size: 0x%05lx\n" " Memory Flush Stride: 0x%05lx\n" " Duty Cycle Index: 0x%03x\n" " Duty Cycle Index Width: 0x%03x\n" " Day Alarm Index: 0x%03x\n" " Month Alarm Index: 0x%03x\n" " Century byte (CMOS): 0x%03x\n" " Boot Architecture: 0x%04x\n" " Flags: 0x%08lx\n", Address + sizeof(DESCRIPTION_HEADER), fadt.facs, fadt.dsdt, (fadt.int_model == 0 ? "Dual PIC" : "Multiple APIC" ), fadt.sci_int_vector, fadt.smi_cmd_io_port, fadt.acpi_on_value, fadt.acpi_off_value, fadt.s4bios_req, fadt.pm1a_evt_blk_io_port, fadt.pm1b_evt_blk_io_port, fadt.pm1_evt_len, fadt.pm1a_ctrl_blk_io_port, fadt.pm1b_ctrl_blk_io_port, fadt.pm1_ctrl_len, fadt.pm2_ctrl_blk_io_port, fadt.pm2_ctrl_len, fadt.pm_tmr_blk_io_port, fadt.pm_tmr_len, fadt.gp0_blk_io_port, fadt.gp0_blk_len, fadt.gp1_blk_io_port, fadt.gp1_blk_len, fadt.gp1_base, fadt.lvl2_latency, fadt.lvl3_latency, #ifndef _IA64_ // XXTF fadt.flush_size, fadt.flush_stride, fadt.duty_offset, fadt.duty_width, #endif fadt.day_alarm_index, fadt.month_alarm_index, fadt.century_alarm_index, #ifndef _IA64_ // XXTF fadt.boot_arch, #endif fadt.flags ); if (fadt.flags & WRITEBACKINVALIDATE_WORKS) { dprintf(" Write Back Invalidate is supported\n"); } if (fadt.flags & WRITEBACKINVALIDATE_DOESNT_INVALIDATE) { dprintf(" Write Back Invalidate doesn't invalidate the caches\n"); } if (fadt.flags & SYSTEM_SUPPORTS_C1) { dprintf(" System cupports C1 Power state on all processors\n"); } if (fadt.flags & P_LVL2_UP_ONLY) { dprintf(" System supports C2 in MP and UP configurations\n"); } if (fadt.flags & PWR_BUTTON_GENERIC) { dprintf(" Power Button is treated as a generic feature\n"); } if (fadt.flags & SLEEP_BUTTON_GENERIC) { dprintf(" Sleep Button is treated as a generic feature\n"); } if (fadt.flags & RTC_WAKE_GENERIC) { dprintf(" RTC Wake is not supported in fixed register space\n"); } if (fadt.flags & RTC_WAKE_FROM_S4) { dprintf(" RTC Wake can work from an S4 state\n"); } if (fadt.flags & TMR_VAL_EXT) { dprintf(" TMR_VAL implemented as 32-bit value\n"); } #ifndef _IA64_ // XXTF if (fadt.Header.Revision > 1) { if (!(fadt.boot_arch & LEGACY_DEVICES)) { dprintf(" The machine does not contain legacy ISA devices\n"); } if (!(fadt.boot_arch & I8042)) { dprintf(" The machine does not contain a legacy i8042\n"); } if (fadt.flags & RESET_CAP) { dprintf(" The reset register is supported\n"); dprintf(" Reset Val: %x\n", fadt.reset_val); switch (fadt.reset_reg.AddressSpaceID) { case 0: addressSpace = "Memory"; break; case 1: addressSpace = "I/O"; break; case 2: addressSpace = "PCIConfig"; break; default: addressSpace = "undefined"; } dprintf(" Reset register: %s - %08x'%08x\n", addressSpace, fadt.reset_reg.Address.HighPart, fadt.reset_reg.Address.LowPart ); } } #endif return; } VOID dumpGBL( ULONG Verbose ) /*++ Routine Description: This routine reads in all the system tables and prints out what the ACPI Good Bios List Entry for this machine should be Arguments: None Return Value: None --*/ { ACPIInformation inf; BOOL status; DESCRIPTION_HEADER hdr; ULONG64 dateAddress; PRSDTINFORMATION info; PUCHAR tempPtr; ULONG i; ULONG numElements; ULONG returnLength; ULONG size; ULONG_PTR address; ULONG_PTR address2; // // Remember where the date address is stored // dateAddress = 0xFFFF5; // // Make sure that we can read the pointer // address2 = GetExpression( "ACPI!RsdtInformation" ); if (!address2) { dprintf("dumpGBL: Could not find RsdtInformation\n"); return; } status = GetUlongPtr( "ACPI!RsdtInformation", &address ); if (status == FALSE || !address) { dprintf("dumpGBL: No RsdtInformation present\n"); return; } // // Read the ACPInformation table, so that we know where the RSDT lives // status = GetUlongPtr( "ACPI!AcpiInformation", &address2 ); if (status == FALSE || !address2) { dprintf("dumpGBL: Could not read AcpiInformation\n"); return; } status = ReadMemory( address2, &inf, sizeof(ACPIInformation), &returnLength ); if (!status || returnLength != sizeof(ACPIInformation)) { dprintf("dumpGBL: Could not read AcpiInformation- %d %x\n", status, returnLength); return; } // // Read in the header for the RSDT // address2 = (ULONG_PTR) inf.RootSystemDescTable; status = ReadMemory( address2, &hdr, sizeof(DESCRIPTION_HEADER), &returnLength ); if (!status || returnLength != sizeof(DESCRIPTION_HEADER)) { dprintf("dumpGBL: Could not read RSDT @%x - %d %x\n", address2, status, returnLength ); return; } // // The number of elements in the table is the first entry // in the structure // status = ReadMemory(address, &numElements, sizeof(ULONG), &returnLength); if (status == FALSE || returnLength != sizeof(ULONG) ) { dprintf("dumpGBL: Could not read RsdtInformation\n"); return; } // // If there are no elements, then return // if (numElements == 0) { dprintf("dumpGBL: No tables the RsdtInformation\n"); return; } // // Allocate the table, and read in all the pointers // size = sizeof(RSDTINFORMATION) + ( (numElements - 1) * sizeof(RSDTELEMENT) ); info = LocalAlloc( LPTR, size ); if (info == NULL) { dprintf("dumpGBL: Could not allocate %x bytes for table\n", size); return; } // // Read the entire table // status = ReadMemory( address, info, size, &returnLength ); if (!status || returnLength != size) { dprintf("dumpGBL: Could not read RsdtInformation Table\n"); return; } // // Dump a header so that people know what this is // memset( Buffer, 0, 2048 ); ReadPhysical( dateAddress, Buffer, 8, &returnLength ); dprintf("\nGood Bios List Entry --- Machine BIOS Date %s\n\n", Buffer); memset( Buffer, 0, 2048 ); memcpy( Buffer, hdr.OEMID, 6); tempPtr = Buffer; while (*tempPtr) { if (*tempPtr == ' ') { *tempPtr = '\0'; break; } tempPtr++; } memcpy( tempPtr, hdr.OEMTableID, 8 ); while (*tempPtr) { if (*tempPtr == ' ') { *tempPtr = '\0'; break; } tempPtr++; } ReadPhysical( dateAddress, tempPtr, 8, &returnLength ); while (*tempPtr) { if (*tempPtr == ' ') { *tempPtr = '\0'; break; } tempPtr++; } // // This is the entry name // dprintf("[%s]\n", Buffer ); // // Dump the all the tables that are loaded in the RSDT table // for (i = 0; i < numElements; i++) { if (!(info->Tables[i].Flags & RSDTELEMENT_MAPPED) ) { continue; } dumpGBLEntry( (ULONG_PTR) info->Tables[i].Address, Verbose ); } // // Dump the entry for the RSDT // dumpGBLEntry( (ULONG_PTR) inf.RootSystemDescTable, Verbose ); // // Add some whitespace // dprintf("\n"); // // Free the RSDT information structure // LocalFree( info ); // // Done // return; } VOID dumpGBLEntry( IN ULONG_PTR Address, IN ULONG Verbose ) /*++ Routine Description: This routine actually prints the rule for the table at the specified address Arguments: Address - where the table is located Return Value: None --*/ { BOOL status; DESCRIPTION_HEADER header; ULONG returnLength; UCHAR tableId[7]; UCHAR entryId[20]; // // Read the header for the table // status = ReadMemory( Address, &header, sizeof(DESCRIPTION_HEADER), &returnLength ); if (!status || returnLength != sizeof(DESCRIPTION_HEADER)) { dprintf("dumpGBLEntry: %x - can't read header\n", Address ); return; } // // Don't print out a table unless its the FACP or we are being verbose // if (!(Verbose & VERBOSE_2) && header.Signature != FADT_SIGNATURE) { return; } // // Initialize the table id field // memset( tableId, 0, 7 ); tableId[0] = '\"'; memcpy( &tableId[1], &(header.Signature), sizeof(ULONG) ); strcat( tableId, "\"" ); // // Get the entry ready for the OEM Id // memset( entryId, 0, 20 ); entryId[0] = '\"'; memcpy( &entryId[1], header.OEMID, 6 ); strcat( entryId, "\""); dprintf("AcpiOemId=%s,%s\n", tableId, entryId ); // // Get the entry ready for the OEM Table Id // memset( entryId, 0, 20 ); entryId[0] = '\"'; memcpy( &entryId[1], header.OEMTableID, 8 ); strcat( entryId, "\""); dprintf("AcpiOemTableId=%s,%s\n", tableId, entryId ); // // Get the entry ready for the OEM Revision // dprintf("AcpiOemRevision=\">=\",%s,%x\n", tableId, header.OEMRevision ); // // Get the entry ready for the ACPI revision // if (header.Revision != 1) { dprintf("AcpiRevision=\">=\",%s,%x\n", tableId, header.Revision ); } // // Get the entry ready for the ACPI Creator Revision // dprintf("AcpiCreatorRevision=\">=\",%s,%x\n", tableId, header.CreatorRev ); } VOID dumpHeader( IN ULONG_PTR Address, IN PDESCRIPTION_HEADER Header, IN BOOLEAN Verbose ) /*++ Routine Description: This function dumps out a table header Arugments: Address - Where the table is located Header - The table header Verbose - How much information to give Return Value: NULL --*/ { memset( Buffer, 0, 2048 ); memcpy( Buffer, &(Header->Signature), sizeof(ULONG) ); if (Verbose) { dprintf( "HEADER - %#08lx\n" " Signature: %s\n" " Length: 0x%08lx\n" " Revision: 0x%02x\n" " Checksum: 0x%02x\n", Address, Buffer, Header->Length, Header->Revision, Header->Checksum ); memset( Buffer, 0, 7 ); memcpy( Buffer, Header->OEMID, 6 ); dprintf(" OEMID: %s\n", Buffer ); memcpy( Buffer, Header->OEMTableID, 8 ); dprintf(" OEMTableID: %s\n", Buffer ); dprintf(" OEMRevision: 0x%08lx\n", Header->OEMRevision ); memset( Buffer, 0, 8 ); memcpy( Buffer, Header->CreatorID, 4 ); dprintf(" CreatorID: %s\n", Buffer ); dprintf(" CreatorRev: 0x%08lx\n", Header->CreatorRev ); } else { dprintf( " %s @(%#08lx) Rev: %#03x Len: %#08lx", Buffer, Address, Header->Revision, Header->Length ); memset( Buffer, 0, sizeof(ULONG) ); memcpy( Buffer, Header->OEMTableID, 8 ); dprintf(" TableID: %s\n", Buffer ); } return; } VOID dumpMAPIC( IN ULONG_PTR Address ) /*++ Routine Description: This dumps the multiple apic table Arguments: Address of the table Return Value: None --*/ { BOOL hasMPSFlags; BOOL status; BOOL virtualMemory; DESCRIPTION_HEADER mapicHeader; PIOAPIC ioApic; PISA_VECTOR interruptSourceOverride; PMAPIC mapic; PIO_NMISOURCE nmiSource; PLOCAL_NMISOURCE localNmiSource; PPROCLOCALAPIC localApic; PUCHAR buffer; PUCHAR limit; ULONG index; ULONG returnLength; ULONG flags; // // First check to see if we find the correct things // dprintf("MAPIC - "); for (index = 0; index < 2; index++) { status = ReadPhysicalOrVirtual( Address, &mapicHeader, sizeof(DESCRIPTION_HEADER), &returnLength, (BOOL) index ); if (!status || mapicHeader.Signature != APIC_SIGNATURE) { continue; } else { break; } } // // This will set the policy for the rest of the operation // switch (index) { case 0: virtualMemory = FALSE; break; case 1: virtualMemory = TRUE; break; default: if (!status) { dprintf( "dumpMAPIC: Could only read 0x%08lx of 0x%08lx bytes\n", returnLength, sizeof(DESCRIPTION_HEADER) ); } else { dprintf( "dumpMAPIC: Invalid Signature 0x%08lx != ACPI_SIGNATURE\n", mapicHeader.Signature ); dumpHeader( Address, &mapicHeader, TRUE ); } return; } // switch // // Do we have a correctly sized data structure // mapic = LocalAlloc( LPTR, mapicHeader.Length ); if (mapic == NULL) { dprintf( "%#08lx: Could not allocate %#08lx bytes\n", Address, mapicHeader.Length ); dumpHeader( Address, &mapicHeader, TRUE ); return; } // // Read the data // status = ReadPhysicalOrVirtual( Address, mapic, mapicHeader.Length, &returnLength, virtualMemory ); if (!status) { dprintf( "dumpMAPIC: Read %#08lx of %#08lx bytes\n", Address, returnLength, mapicHeader.Length ); dumpHeader( Address, &mapicHeader, TRUE ); LocalFree( mapic ); return; } // // At this point, we are confident that everything worked // dumpHeader( Address, &(mapic->Header), TRUE ); dprintf("MAPIC - BODY - %#08lx\n", Address + sizeof(DESCRIPTION_HEADER) ); dprintf(" Local APIC Address: %#08lx\n", mapic->LocalAPICAddress ); dprintf(" Flags: %#08lx\n", mapic->Flags ); if (mapic->Flags & PCAT_COMPAT) { dprintf(" PC-AT dual 8259 compatible setup\n"); } buffer = (PUCHAR) &(mapic->APICTables[0]); limit = (PUCHAR) ( (ULONG_PTR)mapic + mapic->Header.Length ); while (buffer < limit) { // // Assume that no flags are set // hasMPSFlags = FALSE; // // Lets see what kind of table we have? // localApic = (PPROCLOCALAPIC) buffer; ioApic = (PIOAPIC) buffer; interruptSourceOverride = (PISA_VECTOR) buffer; nmiSource = (PIO_NMISOURCE) buffer; localNmiSource = (PLOCAL_NMISOURCE) buffer; // // Is it a localApic? // if (localApic->Type == PROCESSOR_LOCAL_APIC) { buffer += localApic->Length; dprintf( " Processor Local Apic\n" " ACPI Processor ID: 0x%02x\n" " APIC ID: 0x%02x\n" " Flags: 0x%08lx\n", localApic->ACPIProcessorID, localApic->APICID, localApic->Flags ); if (localApic->Flags & PLAF_ENABLED) { dprintf(" Processor is Enabled\n"); } if (localApic->Length != PROCESSOR_LOCAL_APIC_LENGTH) { dprintf( " Local Apic has length 0x%x instead of 0x%x\n", localApic->Length, PROCESSOR_LOCAL_APIC_LENGTH ); break; } } else if (ioApic->Type == IO_APIC) { buffer += ioApic->Length; dprintf( " IO Apic\n" " IO APIC ID: 0x%02x\n" " IO APIC ADDRESS: 0x%08lx\n" " System Vector Base: 0x%08lx\n", ioApic->IOAPICID, ioApic->IOAPICAddress, ioApic->SystemVectorBase ); if (ioApic->Length != IO_APIC_LENGTH) { dprintf( " IO Apic has length 0x%x instead of 0x%x\n", ioApic->Length, IO_APIC_LENGTH ); break; } } else if (interruptSourceOverride->Type == ISA_VECTOR_OVERRIDE) { buffer += interruptSourceOverride->Length; dprintf( " Interrupt Source Override\n" " Bus: 0x%02x\n" " Source: 0x%02x\n" " Global Interrupt: 0x%08lx\n" " Flags: 0x%04x\n", interruptSourceOverride->Bus, interruptSourceOverride->Source, interruptSourceOverride->GlobalSystemInterruptVector, interruptSourceOverride->Flags ); if (interruptSourceOverride->Length != ISA_VECTOR_OVERRIDE_LENGTH) { dprintf( " Interrupt Source Override has length 0x%x instead of 0x%x\n", interruptSourceOverride->Length, ISA_VECTOR_OVERRIDE_LENGTH ); break; } hasMPSFlags = TRUE; flags = interruptSourceOverride->Flags; } else if (nmiSource->Type == IO_NMI_SOURCE) { buffer += nmiSource->Length; dprintf( " Non Maskable Interrupt Source - on I/O APIC\n" " Flags: 0x%02x\n" " Global Interrupt: 0x%08lx\n", nmiSource->Flags, nmiSource->GlobalSystemInterruptVector ); if (nmiSource->Length != IO_NMI_SOURCE_LENGTH) { dprintf( " Non Maskable Interrupt source has length 0x%x instead of 0x%x\n", nmiSource->Length, IO_NMI_SOURCE_LENGTH ); break; } hasMPSFlags = TRUE; flags = nmiSource->Flags; } else if (localNmiSource->Type == LOCAL_NMI_SOURCE) { buffer += localNmiSource->Length; dprintf( " Non Maskable Interrupt Source - local to processor\n" " Flags: 0x%04x\n" " Processor: 0x%02x %s\n" " LINTIN: 0x%02x\n", localNmiSource->Flags, localNmiSource->ProcessorID, localNmiSource->ProcessorID == 0xff ? "(all)" : "", localNmiSource->LINTIN ); if (localNmiSource->Length != LOCAL_NMI_SOURCE_LENGTH) { dprintf( " Non Maskable Interrupt source has length 0x%x instead of 0x%x\n", localNmiSource->Length, IO_NMI_SOURCE_LENGTH ); break; } hasMPSFlags = TRUE; flags = localNmiSource->Flags; } else { dprintf(" UNKOWN RECORD\n"); dprintf(" Length: 0x%8lx\n", ioApic->Length ); buffer += ioApic->Length; } // // Do we have any flags to dump out? // if (hasMPSFlags) { switch (flags & PO_BITS) { case POLARITY_HIGH: dprintf(" POLARITY_HIGH\n"); break; case POLARITY_LOW: dprintf(" POLARITY_LOW\n"); break; case POLARITY_CONFORMS_WITH_BUS: dprintf(" POLARITY_CONFORMS_WITH_BUS\n"); break; default: dprintf(" POLARITY_UNKNOWN\n"); break; } switch (flags & EL_BITS) { case EL_EDGE_TRIGGERED: dprintf(" EL_EDGE_TRIGGERED\n"); break; case EL_LEVEL_TRIGGERED: dprintf(" EL_LEVEL_TRIGGERED\n"); break; case EL_CONFORMS_WITH_BUS: dprintf(" EL_CONFORMS_WITH_BUS\n"); break; default: dprintf(" EL_UNKNOWN\n"); break; } } } LocalFree( mapic ); return; } VOID dumpRSDT( IN ULONG_PTR Address ) /*++ Routine Description: This search the dumps the RSDT table Arguments: Pointer to the table Return Value: NONE --*/ { BOOL status; BOOL virtualMemory = FALSE; DESCRIPTION_HEADER rsdtHeader; PRSDT rsdt; ULONG index; ULONG numEntries; ULONG returnLength; dprintf("RSDT - "); // // Determine if we have virtual or physical memory // for (index = 0; index < 2; index++) { status = ReadPhysicalOrVirtual( Address, &rsdtHeader, sizeof(DESCRIPTION_HEADER), &returnLength, (BOOL) index ); if (!status || rsdtHeader.Signature != RSDT_SIGNATURE) { continue; } else { break; } } // // This will set the policy for the rest of the operation // switch (index) { case 0: virtualMemory = FALSE; break; case 1: virtualMemory = TRUE; break; default: if (!status) { dprintf( "dumpRSDT: Could only read 0x%08lx of 0x%08lx bytes\n", returnLength, sizeof(DESCRIPTION_HEADER) ); } else { dprintf( "dumpRSDT: Invalid Signature 0x%08lx != RSDT_SIGNATURE\n", rsdtHeader.Signature ); dumpHeader( Address, &rsdtHeader, TRUE ); } return; } // switch // // Do we have a correctly sized data structure // rsdt = LocalAlloc( LPTR, rsdtHeader.Length ); if (rsdt == NULL) { dprintf( "dumpRSDT: Could not allocate %#08lx bytes\n", Address, rsdtHeader.Length ); dumpHeader( Address, &rsdtHeader, TRUE ); return; } // // Read the data // status = ReadPhysicalOrVirtual( Address, rsdt, rsdtHeader.Length, &returnLength, virtualMemory ); if (!status) { dprintf( "dumpRSDT: Read %#08lx of %#08lx bytes\n", Address, returnLength, rsdtHeader.Length ); dumpHeader( Address, &rsdtHeader, TRUE ); LocalFree( rsdt ); return; } else if (rsdt->Header.Signature != RSDT_SIGNATURE) { dprintf( "dumpRSDT: Signature (%#08lx) != RSDT_SIGNATURE (%#08lx)\n", Address, rsdt->Header.Signature, RSDT_SIGNATURE ); dumpHeader( Address, &rsdtHeader, TRUE ); LocalFree( rsdt ); return; } // // At this point, we are confident that everything worked // dumpHeader( Address, &(rsdt->Header), TRUE ); dprintf("RSDT - BODY - %#08lx\n", Address + sizeof(DESCRIPTION_HEADER) ); numEntries = ( rsdt->Header.Length - sizeof(DESCRIPTION_HEADER) ) / sizeof(rsdt->Tables[0]); for (index = 0; index < numEntries; index++) { // // Note: unless things radically change, the pointers in the // rsdt will always point to bios memory! // status = ReadPhysicalOrVirtual( rsdt->Tables[index], &rsdtHeader, sizeof(DESCRIPTION_HEADER), &returnLength, FALSE ); if (!status || returnLength != sizeof(DESCRIPTION_HEADER)) { dprintf( "dumpRSDT: [%d:0x%08lx] - Read %#08lx of %#08lx bytes\n", index, rsdt->Tables[index], returnLength, sizeof(DESCRIPTION_HEADER) ); continue; } dumpHeader( rsdt->Tables[index], &rsdtHeader, FALSE ); } LocalFree( rsdt ); return; } BOOLEAN findRSDT( IN PULONG_PTR Address ) /*++ Routine Description: This searchs the memory on the target system for the RSDT pointer Arguments: Address - Where to store the result Return Value: TRUE - If we found the RSDT --*/ { PHYSICAL_ADDRESS address = { 0L, 0L }; RSDP rsdp; RSDT rsdt; UCHAR index; UCHAR sum; ULONG limit; ULONG returnLength; ULONG start; // // Calculate the start and end of the search range // start = (ULONG) RSDP_SEARCH_RANGE_BEGIN; limit = (ULONG) start + RSDP_SEARCH_RANGE_LENGTH - RSDP_SEARCH_INTERVAL; dprintf( "Searching for RSDP."); // // Loop for a while // for (; start <= limit; start += RSDP_SEARCH_INTERVAL) { if (start % (RSDP_SEARCH_INTERVAL * 100 ) == 0) { dprintf("."); } // // Read the data from the target // address.LowPart = start; ReadPhysical( address.QuadPart, &rsdp, sizeof(RSDP), &returnLength); if (returnLength != sizeof(RSDP)) { dprintf( "%#08lx: Read %#08lx of %#08lx bytes\n", start, returnLength, sizeof(RSDP) ); return FALSE; } // // Is this a match? // if (rsdp.Signature != RSDP_SIGNATURE) { continue; } // // Check the checksum out // for (index = 0, sum = 0; index < sizeof(RSDP); index++) { sum = (UCHAR) (sum + *( (UCHAR *) ( (ULONG_PTR) &rsdp + index ) ) ); } if (sum != 0) { continue; } // // Found RSDP // dprintf("\nRSDP - %#08lx\n", start ); memset( Buffer, 0, 2048 ); memcpy( Buffer, &(rsdp.Signature), sizeof(ULONGLONG) ); dprintf(" Signature: %s\n", Buffer ); dprintf(" Checksum: %#03x\n", rsdp.Checksum ); memset( Buffer, 0, sizeof(ULONGLONG) ); memcpy( Buffer, rsdp.OEMID, 6 ); dprintf(" OEMID: %s\n", Buffer ); dprintf(" Reserved: %#03x\n", rsdp.Reserved ); dprintf(" RsdtAddress: %#08lx\n", rsdp.RsdtAddress ); // // Done // *Address = rsdp.RsdtAddress; return TRUE; } return FALSE; }