/*++ Copyright (c) 2000 Microsoft Corporation Module Name: acpi.c Abstract: WinDbg Extension Api for interpretting ACPI data structures Supports rsdt, fadt, facs, mapic, gbl and inf Author: Ported to 64 bit by Graham Laverty (t-gralav) 10-Mar-2000 Based on Code by: Stephane Plante (splante) 21-Mar-1997 Peter Wieland (peterwie) 16-Oct-1995 Ken Reneris (kenr) 06-June-1994 Environment: User Mode. Revision History: Ported to 64 bit by Graham Laverty (t-gralav) 10-Mar-2000 --*/ #include "precomp.h" #pragma hdrstop // Needed ? (what does it do?) // // Verbose flags (for device extensions) // #define VERBOSE_1 0x01 #define VERBOSE_2 0x02 // // BUG BUG // These need to be converted to enums in the ACPI Driver // #define DATAF_BUFF_ALIAS 0x00000001 #define DATAF_GLOBAL_LOCK 0x00000002 #define OBJTYPE_UNKNOWN 0x00 #define OBJTYPE_INTDATA 0x01 #define OBJTYPE_STRDATA 0x02 #define OBJTYPE_BUFFDATA 0x03 #define OBJTYPE_PKGDATA 0x04 #define OBJTYPE_FIELDUNIT 0x05 #define OBJTYPE_DEVICE 0x06 #define OBJTYPE_EVENT 0x07 #define OBJTYPE_METHOD 0x08 #define OBJTYPE_MUTEX 0x09 #define OBJTYPE_OPREGION 0x0a #define OBJTYPE_POWERRES 0x0b #define OBJTYPE_PROCESSOR 0x0c #define OBJTYPE_THERMALZONE 0x0d #define OBJTYPE_BUFFFIELD 0x0e #define OBJTYPE_DDBHANDLE 0x0f #define OBJTYPE_DEBUG 0x10 #define OBJTYPE_INTERNAL 0x80 #define OBJTYPE_OBJALIAS (OBJTYPE_INTERNAL + 0x00) #define OBJTYPE_DATAALIAS (OBJTYPE_INTERNAL + 0x01) #define OBJTYPE_BANKFIELD (OBJTYPE_INTERNAL + 0x02) #define OBJTYPE_FIELD (OBJTYPE_INTERNAL + 0x03) #define OBJTYPE_INDEXFIELD (OBJTYPE_INTERNAL + 0x04) #define OBJTYPE_DATA (OBJTYPE_INTERNAL + 0x05) #define OBJTYPE_DATAFIELD (OBJTYPE_INTERNAL + 0x06) #define OBJTYPE_DATAOBJ (OBJTYPE_INTERNAL + 0x07) // definition of FADT.flags bits // this one bit flag indicates whether or not the WBINVD instruction works properly,if this bit is not set we can not use S2, S3 states, or // C3 on MP machines #define WRITEBACKINVALIDATE_WORKS_BIT 0 #define WRITEBACKINVALIDATE_WORKS (1 << WRITEBACKINVALIDATE_WORKS_BIT) // this flag indicates if wbinvd works EXCEPT that it does not invalidate the cache #define WRITEBACKINVALIDATE_DOESNT_INVALIDATE_BIT 1 #define WRITEBACKINVALIDATE_DOESNT_INVALIDATE (1 << WRITEBACKINVALIDATE_DOESNT_INVALIDATE_BIT) // this flag indicates that the C1 state is supported on all processors. #define SYSTEM_SUPPORTS_C1_BIT 2 #define SYSTEM_SUPPORTS_C1 (1 << SYSTEM_SUPPORTS_C1_BIT) // this one bit flag indicates whether support for the C2 state is restricted to uniprocessor machines #define P_LVL2_UP_ONLY_BIT 3 #define P_LVL2_UP_ONLY (1 << P_LVL2_UP_ONLY_BIT) // this bit indicates whether the PWR button is treated as a fix feature (0) or a generic feature (1) #define PWR_BUTTON_GENERIC_BIT 4 #define PWR_BUTTON_GENERIC (1 << PWR_BUTTON_GENERIC_BIT) #define SLEEP_BUTTON_GENERIC_BIT 5 #define SLEEP_BUTTON_GENERIC (1 << SLEEP_BUTTON_GENERIC_BIT) // this bit indicates whether the RTC wakeup status is reported in fix register space (0) or not (1) #define RTC_WAKE_GENERIC_BIT 6 #define RTC_WAKE_GENERIC (1 << RTC_WAKE_GENERIC_BIT) #define RTC_WAKE_FROM_S4_BIT 7 #define RTC_WAKE_FROM_S4 (1 << RTC_WAKE_FROM_S4_BIT) // This bit indicates whether the machine implements a 24 or 32 bit timer. #define TMR_VAL_EXT_BIT 8 #define TMR_VAL_EXT (1 << TMR_VAL_EXT_BIT) // This bit indicates whether the machine supports docking //#define DCK_CAP_BIT 9 //#define DCK_CAP (1 << DCK_CAP_BIT) // This bit indicates whether the machine supports reset #define RESET_CAP_BIT 10 #define RESET_CAP (1 << RESET_CAP_BIT) // // Definition of FADT.boot_arch flags // #define LEGACY_DEVICES 1 #define I8042 2 // // Verbose flags (for contexts) // #define VERBOSE_CONTEXT 0x01 #define VERBOSE_CALL 0x02 #define VERBOSE_HEAP 0x04 #define VERBOSE_OBJECT 0x08 #define VERBOSE_NSOBJ 0x10 #define VERBOSE_RECURSE 0x20 UCHAR Buffer[2048]; #define RSDP_SIGNATURE 0x2052545020445352 // "RSD PTR " #define RSDT_SIGNATURE 0x54445352 // "RSDT" #define FADT_SIGNATURE 0x50434146 // "FACP" #define FACS_SIGNATURE 0x53434146 // "FACS" #define APIC_SIGNATURE 0x43495041 // "APIC" #ifndef NEC_98 #define RSDP_SEARCH_RANGE_BEGIN 0xE0000 // physical address where we begin searching for the RSDP #else // NEC_98 #define RSDP_SEARCH_RANGE_BEGIN 0xE8000 // physical address where we begin searching for the RSDP #endif // NEC_98 #define RSDP_SEARCH_RANGE_END 0xFFFFF #define RSDP_SEARCH_RANGE_LENGTH (RSDP_SEARCH_RANGE_END-RSDP_SEARCH_RANGE_BEGIN+1) #define RSDP_SEARCH_INTERVAL 16 // search on 16 byte boundaries // FACS Stuff ************************************************************************************ // FACS Flags definitions #define FACS_S4BIOS_SUPPORTED_BIT 0 // flag indicates whether or not the BIOS will save/restore memory around S4 #define FACS_S4BIOS_SUPPORTED (1 << FACS_S4BIOS_SUPPORTED_BIT) // FACS.GlobalLock bit field definitions #define GL_PENDING_BIT 0x00 #define GL_PENDING (1 << GL_PENDING_BIT) #define GL_OWNER_BIT 0x01 #define GL_OWNER (1 << GL_OWNER_BIT) //#define GL_NON_RESERVED_BITS_MASK (GL_PENDING+GL_OWNED) // MAPIC Stuff ************************************************************************************ // Multiple APIC description table // Multiple APIC structure flags #define PCAT_COMPAT_BIT 0 // indicates that the system also has a dual 8259 pic setup. #define PCAT_COMPAT (1 << PCAT_COMPAT_BIT) // APIC Structure Types #define PROCESSOR_LOCAL_APIC 0 #define IO_APIC 1 #define ISA_VECTOR_OVERRIDE 2 #define IO_NMI_SOURCE 3 #define LOCAL_NMI_SOURCE 4 #define ADDRESS_EXTENSION_STRUCTURE 5 #define IO_SAPIC 6 #define LOCAL_SAPIC 7 #define PLATFORM_INTERRUPT_SOURCE 8 #define PROCESSOR_LOCAL_APIC_LENGTH 8 #define IO_APIC_LENGTH 12 #define ISA_VECTOR_OVERRIDE_LENGTH 10 #define IO_NMI_SOURCE_LENGTH 8 #define LOCAL_NMI_SOURCE_LENGTH 6 #define PLATFORM_INTERRUPT_SOURCE_LENGTH 16 #define IO_SAPIC_LENGTH 16 #define PROCESSOR_LOCAL_SAPIC_LENGTH 12 // Platform Interrupt Types #define PLATFORM_INT_PMI 1 #define PLATFORM_INT_INIT 2 #define PLATFORM_INT_CPE 3 // Processor Local APIC Flags #define PLAF_ENABLED_BIT 0 #define PLAF_ENABLED (1 << PLAF_ENABLED_BIT) // These defines come from the MPS 1.4 spec, section 4.3.4 and they are referenced as // such in the ACPI spec. #define PO_BITS 3 #define POLARITY_HIGH 1 #define POLARITY_LOW 3 #define POLARITY_CONFORMS_WITH_BUS 0 #define EL_BITS 0xc #define EL_BIT_SHIFT 2 #define EL_EDGE_TRIGGERED 4 #define EL_LEVEL_TRIGGERED 0xc #define EL_CONFORMS_WITH_BUS 0 #define FADT_REV_1_SIZE 116 #define FADT_REV_2_SIZE 129 #define FADT_REV_3_SIZE 244 // GBL Stuff ************************************************************************************ // // This structure lets us know the state of one entry in the RSDT // // INF Stuff ************************************************************************************ // // descriptions of bits in ACPIInformation.ACPI_Flags // #define C2_SUPPORTED_BIT 3 #define C2_SUPPORTED (1 << C2_SUPPORTED_BIT) #define C3_SUPPORTED_BIT 4 #define C3_SUPPORTED (1 << C3_SUPPORTED_BIT) #define C3_PREFERRED_BIT 5 #define C3_PREFERRED (1 << C3_PREFERRED_BIT) // // descriptions of bits in ACPIInformation.ACPI_Capabilities // #define CSTATE_C1_BIT 4 #define CSTATE_C1 (1 << CSTATE_C1_BIT) #define CSTATE_C2_BIT 5 #define CSTATE_C2 (1 << CSTATE_C2_BIT) #define CSTATE_C3_BIT 6 #define CSTATE_C3 (1 << CSTATE_C3_BIT) #define DUMP_FLAG_NO_INDENT 0x000001 #define DUMP_FLAG_NO_EOL 0x000002 #define DUMP_FLAG_SINGLE_LINE 0x000004 #define DUMP_FLAG_TABLE 0x000008 #define DUMP_FLAG_LONG_NAME 0x000010 #define DUMP_FLAG_SHORT_NAME 0x000020 #define DUMP_FLAG_SHOW_BIT 0x000040 #define DUMP_FLAG_ALREADY_INDENTED 0x000080 typedef struct _FLAG_RECORD { ULONGLONG Bit; PCCHAR ShortName; PCCHAR LongName; PCCHAR NotShortName; PCCHAR NotLongName; } FLAG_RECORD, *PFLAG_RECORD; FLAG_RECORD PM1ControlFlags[] = { { 0x0001, "", "SCI_EN" , NULL, NULL }, { 0x0002, "", "BM_RLD" , NULL, NULL }, { 0x0004, "", "GBL_RLS" , NULL, NULL }, { 0x0400, "", "SLP_TYP0" , NULL, NULL }, { 0x0800, "", "SLP_TYP1" , NULL, NULL }, { 0x1000, "", "SLP_TYP2" , NULL, NULL }, { 0x2000, "", "SLP_EN" , NULL, NULL }, }; FLAG_RECORD PM1StatusFlags[] = { { 0x0001, "", "TMR_STS" , NULL, NULL }, { 0x0010, "", "BM_STS" , NULL, NULL }, { 0x0020, "", "GBL_STS" , NULL, NULL }, { 0x0100, "", "PWRBTN_STS" , NULL, NULL }, { 0x0200, "", "SLPBTN_STS" , NULL, NULL }, { 0x0400, "", "RTC_STS" , NULL, NULL }, { 0x8000, "", "WAK_STS" , NULL, NULL }, }; FLAG_RECORD PM1EnableFlags[] = { { 0x0001, "", "TMR_EN" , NULL, NULL }, { 0x0020, "", "GBL_EN" , NULL, NULL }, { 0x0100, "", "PWRBTN_EN" , NULL, NULL }, { 0x0200, "", "SLPBTN_EN" , NULL, NULL }, { 0x0400, "", "RTC_EN" , NULL, NULL }, }; #define RSDTELEMENT_MAPPED 0x1 ULONG64 AcpiRsdtAddress = 0; ULONG64 AcpiFadtAddress = 0; ULONG64 AcpiFacsAddress = 0; ULONG64 AcpiMapicAddress = 0; // // Local Function Prototypes // VOID dumpNSObject(IN ULONG64 Address, IN ULONG Verbose, IN ULONG IndentLevel); // // Actual code // BOOL ReadPhysicalOrVirtual( IN ULONG64 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; } BOOLEAN findRSDT( IN PULONG64 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 }; UCHAR index; UCHAR sum; ULONG64 limit; ULONG returnLength = 0; ULONG64 start, initAddress; ULONGLONG compSignature; ULONG addr; int siz; // // Calculate the start and end of the search range // start = RSDP_SEARCH_RANGE_BEGIN; limit = 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("."); if (CheckControlC()) { return FALSE; } } // // Read the data from the target // address.LowPart = (ULONG) start; memset( Buffer, 0, GetTypeSize("hal!_RSDT_32") ); ReadPhysical( address.QuadPart, &Buffer, GetTypeSize("hal!_RSDP"), &returnLength); if (returnLength != GetTypeSize("hal!_RSDP")) { dprintf( "%#08lx: Read %#08lx of %#08lx bytes\n", start, returnLength, GetTypeSize("hal!_RSDP") ); return FALSE; } // // Is this a match? // // INIT TYPE READ PHYSICAL TAKES MAYBE 15 TIME LONGER! initAddress = InitTypeReadPhysical( address.QuadPart, hal!_RSDP ); if ( ReadField(Signature) != RSDP_SIGNATURE) { continue; } // // Check the checksum out // for (index = 0, sum = 0; index < GetTypeSize("hal!_RSDP"); index++) { sum = (UCHAR) (sum + *( (UCHAR *) ( (ULONG64) &Buffer + index ) ) ); } if (sum != 0) { continue; } // // Found RSDP // dprintf("\nRSDP - %016I64x\n", start ); initAddress = InitTypeReadPhysical( address.QuadPart, hal!_RSDP ); // The following error message has been remarked out because the FIRST call to // a InitTypeReadPhysical does NOT access the memory (and returns error 0x01: // MEMORY_READ_ERROR. This is done when ReadField happens, so IT STILL WORKS. // The false error message is a kd bug, and will be fixed in a later build. // Once this has been done, feel free to unremark it. // if (initAddress) { // dprintf("Failed to initialize hal!_RSDP. Error code: %d.", initAddress); // } initAddress = ReadField(Signature); memset( Buffer, 0, 2048 ); memcpy( Buffer, &initAddress, GetTypeSize("ULONGLONG") ); dprintf(" Signature: %s\n", Buffer ); dprintf(" Checksum: %#03x\n", (UCHAR) ReadField(Checksum) ); initAddress = ReadField(OEMID); GetFieldOffset( "hal!_RSDP", "OEMID", &addr); memset( Buffer, 0, GetTypeSize("ULONGLONG") ); ReadPhysical( (address.QuadPart + (ULONG64) addr), &Buffer, 6, &returnLength); if (returnLength != 6) { // 6 is hard-coded in the specs dprintf( "%#08lx: Read %#08lx of 6 bytes in OEMID\n", (address.QuadPart + (ULONG64)addr), returnLength, GetTypeSize("hal!_RSDP") ); return FALSE; } dprintf(" OEMID: %s\n", Buffer ); dprintf(" Reserved: %#02x\n", ReadField(Reserved) ); dprintf(" RsdtAddress: %016I64x\n", ReadField(RsdtAddress) ); // // Done // *Address = ReadField(RsdtAddress);//rsdp.RsdtAddress; return TRUE; } return FALSE; } PUCHAR ReadPhysVirField( IN ULONG64 Address, IN PUCHAR StructName, IN PUCHAR FieldName, IN ULONG Length, IN BOOLEAN Physical ) /*++ Routine Description: This function returns a text string field from physical or virtual memory into Buffer, then returns Buffer Arugments: Address - Where the table is located StructName - Structure name FieldName - Field name Length - Length (number of characters) in field Physical - Read from Physical (TRUE) or Virtual Memory Return Value: String containing contents --*/ { ULONG addr; ULONG returnLength; memset( Buffer, 0, Length + 1); GetFieldOffset( StructName, FieldName, &addr); if (Physical) { ReadPhysical( (Address + (ULONG64) addr), &Buffer, Length, &returnLength); } else { ReadMemory( (Address + (ULONG64) addr), &Buffer, Length, &returnLength); } return Buffer; } VOID dumpHeader( IN ULONG64 Address, IN BOOLEAN Verbose, IN BOOLEAN Physical ) /*++ 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 --*/ { if (Physical) { InitTypeReadPhysical( Address, hal!_DESCRIPTION_HEADER); } else { InitTypeRead( Address, hal!_DESCRIPTION_HEADER); } if (Verbose) { dprintf( "HEADER - %016I64x\n" " Signature: %s\n" " Length: 0x%08lx\n" " Revision: 0x%02x\n" " Checksum: 0x%02x\n", Address, ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "Signature", sizeof(ULONG), Physical), (ULONG) ReadField(Length), (UCHAR) ReadField(Revision), (UCHAR) ReadField(Checksum) ); dprintf(" OEMID: %s\n", ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "OEMID", 6, Physical) ); dprintf(" OEMTableID: %s\n", ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "OEMTableID", 8, Physical) ); dprintf(" OEMRevision: 0x%08lx\n", ReadField(OEMRevision) ); dprintf(" CreatorID: %s\n", ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "CreatorID", 4, Physical) ); dprintf(" CreatorRev: 0x%08lx\n", ReadField(CreatorRev) ); } else { dprintf( " %s @(%016I64x) Rev: %#03x Len: %#08lx", ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "Signature", sizeof(ULONG64), Physical), Address, (UCHAR) ReadField(Revision), (ULONG) ReadField(Length) ); dprintf(" TableID: %s\n", ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "OEMTableID", 8, Physical) ); } return; } VOID dumpRSDT( IN ULONG64 Address, IN BOOLEAN Physical ) /*++ Routine Description: This search the dumps the RSDT table Arguments: Pointer to the table Return Value: NONE --*/ { BOOL status; ULONG64 index; ULONG64 numEntries; ULONG addr; ULONG returnLength = 0; ULONG64 a; dprintf("RSDT - "); if (Physical) { // The following do NOT have their status read as a bug in the return value would give us errors when none exist. The signature check would catch them, anyway. InitTypeReadPhysical( Address, hal!_DESCRIPTION_HEADER); } else { InitTypeRead( Address, hal!_DESCRIPTION_HEADER); } if (ReadField(Signature) != RSDT_SIGNATURE) { dprintf( "dumpRSDT: Invalid Signature 0x%08lx != RSDT_SIGNATURE\n", ReadField(Signature) ); dumpHeader( Address, TRUE, Physical ); return; } dumpHeader( Address, TRUE, Physical ); dprintf("RSDT - BODY - %016I64x\n", Address + GetTypeSize("hal!_DESCRIPTION_HEADER") ); numEntries = ( ReadField(Length) - GetTypeSize("hal!_DESCRIPTION_HEADER") ) / sizeof(ULONG); GetFieldOffset( "hal!_RSDT_32", "Tables", &addr); for (index = 0; index < numEntries; index++) { // // Note: unless things radically change, the pointers in the // rsdt will always point to bios memory! // if (Physical) { ReadPhysical(Address + index + (ULONG64) addr, &a, 4, &returnLength); } else { ReadPointer(Address + index + (ULONG64) addr, &a); } dumpHeader( a, FALSE, TRUE ); } return; } VOID dumpFADT( IN ULONG64 Address ) /*++ Routine Description: This dumps the FADT at the specified address Arguments: The address where the FADT is located at Return Value: NONE --*/ { ULONG fadtLength; ULONG addr; ULONG flags; UCHAR Revision; UCHAR AddressSpaceID; ULONG64 reset_reg_addr; PCHAR addressSpace; BOOLEAN Physical = FALSE; // // First check to see if we find the correct things // dprintf("FADT -- %p", Address); if (Physical) { InitTypeReadPhysical( Address, hal!_DESCRIPTION_HEADER); } else { InitTypeRead( Address, hal!_DESCRIPTION_HEADER); } if (ReadField(Signature) != FADT_SIGNATURE) { dprintf( "dumpRSDT: Invalid Signature 0x%08lx != FADT_SIGNATURE\n", ReadField(Signature) ); dumpHeader( Address, TRUE, Physical ); return; } Revision = (UCHAR)ReadField(Revision); if (Revision == 1) { fadtLength = FADT_REV_1_SIZE; } else if (Revision == 2) { fadtLength = FADT_REV_2_SIZE; } else if (Revision == 3) { fadtLength = FADT_REV_3_SIZE; } else { dprintf("FADT revision is %d, which is not understood by this debugger\n", Revision); fadtLength = FADT_REV_3_SIZE; } // // Do we have a correctly sized data structure // if ((ULONG) ReadField(Length) < fadtLength) { dprintf( "dumpFADT: (%016I64x) Length (%#08lx) is not the size of the FADT (%#08lx)\n", Address, (ULONG) ReadField(Length), fadtLength ); dumpHeader( Address, TRUE, Physical ); return; } // // Dump the table // dumpHeader( Address, TRUE, Physical ); if (Physical) { // Physical/Virtual should have been established above InitTypeReadPhysical( Address, hal!_FADT); } else { InitTypeRead( Address, hal!_FADT); } dprintf( "FADT - BODY - %016I64x\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 + GetTypeSize("hal!_DESCRIPTION_HEADER"), (ULONG) ReadField(facs), (ULONG) ReadField(dsdt), (ReadField(int_model) == 0 ? "Dual PIC" : "Multiple APIC" ), (USHORT) ReadField(sci_int_vector), (ULONG) ReadField(smi_cmd_io_port), (UCHAR) ReadField(acpi_on_value), (UCHAR) ReadField(acpi_off_value), (UCHAR) ReadField(s4bios_req), (ULONG) ReadField(pm1a_evt_blk_io_port), (ULONG) ReadField(pm1b_evt_blk_io_port), (UCHAR) ReadField(pm1_evt_len), (ULONG) ReadField(pm1a_ctrl_blk_io_port), (ULONG) ReadField(pm1b_ctrl_blk_io_port), (UCHAR) ReadField(pm1_ctrl_len), (ULONG) ReadField(pm2_ctrl_blk_io_port), (UCHAR) ReadField(pm2_ctrl_len), (ULONG) ReadField(pm_tmr_blk_io_port), (UCHAR) ReadField(pm_tmr_len), (ULONG) ReadField(gp0_blk_io_port), (UCHAR) ReadField(gp0_blk_len), (ULONG) ReadField(gp1_blk_io_port), (UCHAR) ReadField(gp1_blk_len), (UCHAR) ReadField(gp1_base), (USHORT) ReadField(lvl2_latency), (USHORT) ReadField(lvl3_latency), #ifndef _IA64_ // XXTF (USHORT) ReadField(flush_size), (USHORT) ReadField(flush_stride), (UCHAR) ReadField(duty_offset), (UCHAR) ReadField(duty_width), #endif (UCHAR) ReadField(day_alarm_index), (UCHAR) ReadField(month_alarm_index), (UCHAR) ReadField(century_alarm_index), (USHORT) ReadField(boot_arch), (ULONG) ReadField(flags) ); flags = (ULONG) ReadField(flags); if (flags & WRITEBACKINVALIDATE_WORKS) { dprintf(" Write Back Invalidate is supported\n"); } if (flags & WRITEBACKINVALIDATE_DOESNT_INVALIDATE) { dprintf(" Write Back Invalidate doesn't invalidate the caches\n"); } if (flags & SYSTEM_SUPPORTS_C1) { dprintf(" System supports C1 Power state on all processors\n"); } if (flags & P_LVL2_UP_ONLY) { dprintf(" System supports C2 in MP and UP configurations\n"); } if (flags & PWR_BUTTON_GENERIC) { dprintf(" Power Button is treated as a generic feature\n"); } if (flags & SLEEP_BUTTON_GENERIC) { dprintf(" Sleep Button is treated as a generic feature\n"); } if (flags & RTC_WAKE_GENERIC) { dprintf(" RTC Wake is not supported in fixed register space\n"); } if (flags & RTC_WAKE_FROM_S4) { dprintf(" RTC Wake can work from an S4 state\n"); } if (flags & TMR_VAL_EXT) { dprintf(" TMR_VAL implemented as 32-bit value\n"); } if (Revision > 1) { if (!(ReadField(boot_arch) & LEGACY_DEVICES)) { dprintf(" The machine does not contain legacy ISA devices\n"); } if (!(ReadField(boot_arch) & I8042)) { dprintf(" The machine does not contain a legacy i8042\n"); } if (flags & RESET_CAP) { dprintf(" The reset register is supported\n"); dprintf(" Reset Val: %x\n", ReadField(reset_val)); GetFieldOffset("hal!_FADT", "reset_reg", &addr); GetFieldValue(Address + (ULONG64)addr, "hal!_GEN_ADDR", "AddressSpaceID", AddressSpaceID); switch (AddressSpaceID) { case 0: addressSpace = "Memory"; break; case 1: addressSpace = "I/O"; break; case 2: addressSpace = "PCIConfig"; break; default: addressSpace = "undefined"; } GetFieldOffset("hal!_GEN_ADDR", "Address", &addr); GetFieldValue(Address + (ULONG64)addr, "hal!_LARGE_INTEGER", "QuadPart", reset_reg_addr); dprintf(" Reset register: %s - %016I64x\n", addressSpace, reset_reg_addr ); } } return; } BOOL GetUlongPtr ( IN PCHAR String, IN PULONG64 Address ) { ULONG64 Location; Location = GetExpression( String ); if (!Location) { dprintf("Sorry: Unable to get %s.\n",String); return FALSE; } return ReadPointer(Location, Address); } DECLARE_API( rsdt ) { BOOLEAN Physical = FALSE; if (args != NULL) { AcpiRsdtAddress = GetExpression( args ); // Should work } if (AcpiRsdtAddress == 0) { UINT64 status; // formerly BOOL ULONG64 address; status = GetUlongPtr( "ACPI!AcpiInformation", &address ); if (status == TRUE) { status = GetFieldValue(address,"ACPI!_ACPIInformation","RootSystemDescTable",AcpiRsdtAddress); } } if (AcpiRsdtAddress == 0) { if (!findRSDT( &AcpiRsdtAddress) ) { dprintf("Could not locate the RSDT pointer\n"); return E_INVALIDARG; } Physical = TRUE; } dumpRSDT( AcpiRsdtAddress, Physical ); return S_OK; } DECLARE_API( fadt ) { if (args != NULL && *args != '\0') { AcpiFadtAddress = GetExpression( args ); } if (AcpiFadtAddress == 0) { AcpiFadtAddress = GetExpression( "HAL!HalpFixedAcpiDescTable" ); } if (AcpiFadtAddress == 0) { dprintf("fadt
\n"); return E_INVALIDARG; } dumpFADT( AcpiFadtAddress ); return S_OK; } VOID dumpFACS( IN ULONG64 Address ) /*++ Routine Description: This dumps the FADT at the specified address Arguments: The address where the FADT is located at Return Value: NONE --*/ { BOOLEAN Physical = FALSE; // // Read the data // dprintf("FACS - %016I64x\n", Address); if (Physical) { InitTypeReadPhysical( Address, hal!_FACS); } else { InitTypeRead( Address, hal!_FACS); } if (ReadField(Signature) != FACS_SIGNATURE) { dprintf( "dumpFACS: Invalid Signature 0x%08lx != FACS_SIGNATURE\n", (ULONG) ReadField(Signature) ); return; } // // Dump the table // dprintf( " Signature: %s\n" " Length: %#08lx\n" " Hardware Signature: %#08lx\n" " Firmware Wake Vector: %#08lx\n" " Global Lock : %#08lx\n", ReadPhysVirField(Address, "hal!_FACS", "Signature", sizeof(ULONG), Physical), ReadField(Length), ReadField(HardwareSignature), ReadField(pFirmwareWakingVector), ReadField(GlobalLock) ); if ( (ReadField(GlobalLock) & GL_PENDING) ) { dprintf(" Request for Ownership Pending\n"); } if ( (ReadField(GlobalLock) & GL_OWNER) ) { dprintf(" Global Lock is Owned\n"); } dprintf(" Flags: %#08lx\n", (ULONG) ReadField(Flags) ); if ( (ReadField(Flags) & FACS_S4BIOS_SUPPORTED) ) { dprintf(" S4BIOS_REQ Supported\n"); } return; } DECLARE_API( facs ) { if (args != NULL) { AcpiFacsAddress = GetExpression( args ); } if (AcpiFacsAddress == 0) { BOOL status; UINT64 address; status = GetUlongPtr( "ACPI!AcpiInformation", &address ); if (status == TRUE) { status = GetFieldValue(address,"ACPI!_ACPIInformation","FirmwareACPIControlStructure",AcpiFacsAddress); } } if (AcpiFacsAddress == 0) { dprintf("facs \n"); return E_INVALIDARG; } dumpFACS( AcpiFacsAddress ); return S_OK; } // ReturnXxx Functions - these are just a few functions I wrote that simplify // dealing with certain types of Symbols CHAR ReturnChar( IN ULONG64 Address, IN PUCHAR StructName, IN PUCHAR FieldName ) /*++ Routine Description: Return char using GetFieldValue --*/ { char returnChar; if (GetFieldValue(Address, StructName, FieldName, returnChar)){ // // Failed. try just the base symbols name before giving up // PUCHAR symName=NULL; ULONG i; for(i=strlen(StructName); i > 0 && StructName[i] != '!'; i--); i++; symName = StructName + i; // // Try again // GetFieldValue(Address, symName, FieldName, returnChar); } return returnChar; } ULONG ReturnUSHORT( IN ULONG64 Address, IN PUCHAR StructName, IN PUCHAR FieldName ) /*++ Routine Description: Return USHORT using GetFieldValue --*/ { USHORT returnUSHORT; if (GetFieldValue(Address, StructName, FieldName, returnUSHORT)){ // // Failed. try just the base symbols name before giving up // PUCHAR symName=NULL; ULONG i; for(i=strlen(StructName); i > 0 && StructName[i] != '!'; i--); i++; symName = StructName + i; // // Try again // GetFieldValue(Address, symName, FieldName, returnUSHORT); } return returnUSHORT; } ULONG ReturnULONG( IN ULONG64 Address, IN PUCHAR StructName, IN PUCHAR FieldName ) /*++ Routine Description: Return ULONG using GetFieldValue --*/ { ULONG returnULONG; if (GetFieldValue(Address, StructName, FieldName, returnULONG)){ // // Failed. try just the base symbols name before giving up // PUCHAR symName=NULL; ULONG i; for(i=strlen(StructName); i > 0 && StructName[i] != '!'; i--); i++; symName = StructName + i; // // Try again // GetFieldValue(Address, symName, FieldName, returnULONG); } return returnULONG; } ULONG64 ReturnULONG64( IN ULONG64 Address, IN PUCHAR StructName, IN PUCHAR FieldName ) /*++ Routine Description: Return ULONG64 using GetFieldValue --*/ { ULONG64 returnULONG64; if (GetFieldValue(Address, StructName, FieldName, returnULONG64)){ // // Failed. try just the base symbols name before giving up // PUCHAR symName=NULL; ULONG i; for(i=strlen(StructName); i > 0 && StructName[i] != '!'; i--); i++; symName = StructName + i; // // Try again // GetFieldValue(Address, symName, FieldName, returnULONG64); } return returnULONG64; } VOID dumpMAPIC( IN ULONG64 Address ) /*++ Routine Description: This dumps the multiple apic table Arguments: Address of the table Return Value: None --*/ { BOOL hasMPSFlags; BOOL status; BOOL virtualMemory; ULONG mapicLength; ULONG64 iso; // interruptSourceOverride USHORT isoFlags; ULONG64 buffer; ULONG64 limit; ULONG index; ULONG returnLength; ULONG flags; ULONG get_value; BOOLEAN Physical = FALSE; // // First check to see if we find the correct things // dprintf("MAPIC - "); if (Physical) { InitTypeReadPhysical( Address, hal!_DESCRIPTION_HEADER); } else { InitTypeRead( Address, hal!_DESCRIPTION_HEADER); } if (ReadField(Signature) != APIC_SIGNATURE) { dprintf( "dumpFACS: Invalid Signature 0x%08lx != APIC_SIGNATURE (%x)\n", (ULONG) ReadField(Signature), APIC_SIGNATURE ); return; } mapicLength = (ULONG)ReadField(Length); dumpHeader( Address, TRUE, FALSE ); dprintf("MAPIC - BODY - %016I64x\n", Address + GetTypeSize("hal!_DESCRIPTION_HEADER") ); dprintf(" Local APIC Address: %#08lx\n", ReturnULONG(Address, "hal!_MAPIC","LocalAPICAddress")); GetFieldValue(Address,"hal!_MAPIC","Flags",get_value); dprintf(" Flags: %#08lx\n", get_value ); if (get_value & PCAT_COMPAT) { // Check the flags dprintf(" PC-AT dual 8259 compatible setup\n"); } //gsig2 GetFieldOffset( "hal!_MAPIC", "APICTables", &get_value); buffer = Address + get_value; limit = ( Address + ReadField(Length) ); while (buffer < limit) { if (CheckControlC()) { break; } // // Assume that no flags are set // hasMPSFlags = FALSE; // // Lets see what kind of table we have? // iso = (ULONG64) buffer; // // Is it a localApic? // if (ReturnChar(iso, "acpi!_PROCLOCALAPIC", "Type") == PROCESSOR_LOCAL_APIC) { buffer += ReturnChar(iso, "acpi!_PROCLOCALAPIC", "Length"); dprintf( " Processor Local Apic\n" " ACPI Processor ID: 0x%02x\n" " APIC ID: 0x%02x\n" " Flags: 0x%08lx\n", ReturnChar(iso, "acpi!_PROCLOCALAPIC", "ACPIProcessorID"), ReturnChar(iso, "acpi!_PROCLOCALAPIC", "APICID"), ReturnULONG(iso, "acpi!_PROCLOCALAPIC", "Flags") ); if (ReturnULONG(iso, "acpi!_PROCLOCALAPIC", "Flags") & PLAF_ENABLED) { dprintf(" Processor is Enabled\n"); } if (ReturnChar(iso, "acpi!_PROCLOCALAPIC", "Length") != PROCESSOR_LOCAL_APIC_LENGTH) { dprintf( " Local Apic has length 0x%x instead of 0x%x\n", ReturnChar(iso, "acpi!_PROCLOCALAPIC", "Length"), PROCESSOR_LOCAL_APIC_LENGTH ); break; } } else if (ReturnChar(iso, "hal!_IOAPIC", "Type") == IO_APIC) { buffer += ReturnChar(iso, "hal!_IOAPIC", "Length"); dprintf( " IO Apic\n" " IO APIC ID: 0x%02x\n" " IO APIC ADDRESS: 0x%08lx\n" " System Vector Base: 0x%08lx\n", ReturnChar(iso, "hal!_IOAPIC", "IOAPICID"), ReturnULONG(iso, "hal!_IOAPIC", "IOAPICAddress"), ReturnULONG(iso, "hal!_IOAPIC", "SystemVectorBase") ); if (ReturnChar(iso, "hal!_IOAPIC", "Length") != IO_APIC_LENGTH) { dprintf( " IO Apic has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_IOAPIC", "Length"), IO_APIC_LENGTH ); break; } } else if (ReturnChar(iso,"hal!_ISA_VECTOR","Type") == ISA_VECTOR_OVERRIDE) { buffer += ReturnChar(iso, "hal!_ISA_VECTOR", "Length"); GetFieldValue(iso, "hal!_ISA_VECTOR", "Flags", isoFlags); dprintf( " Interrupt Source Override\n" " Bus: 0x%02x\n" " Source: 0x%02x\n" " Global Interrupt: 0x%08lx\n" " Flags: 0x%04x\n", ReturnChar(iso, "hal!_ISA_VECTOR", "Bus"), ReturnChar(iso, "hal!_ISA_VECTOR", "Source"), ReturnULONG(iso, "hal!_ISA_VECTOR", "GlobalSystemInterruptVector"), isoFlags ); if (ReturnChar(iso,"hal!_ISA_VECTOR","Length") != ISA_VECTOR_OVERRIDE_LENGTH) { dprintf( " Interrupt Source Override has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_ISA_VECTOR", "Length"), ISA_VECTOR_OVERRIDE_LENGTH ); break; } hasMPSFlags = TRUE; flags = isoFlags; } else if (ReturnChar(iso,"acpi!_IO_NMISOURCE","Type") == IO_NMI_SOURCE) { buffer += ReturnChar(iso, "acpi!_IO_NMISOURCE", "Length"); GetFieldValue(iso, "acpi!_IO_NMISOURCE", "Flags", isoFlags); dprintf( " Non Maskable Interrupt Source - on I/O APIC\n" " Flags: 0x%02x\n" " Global Interrupt: 0x%08lx\n", isoFlags, ReturnULONG(iso, "acpi!_IO_NMISOURCE", "GlobalSystemInterruptVector") ); if (ReturnChar(iso,"acpi!_IO_NMISOURCE","Length") != IO_NMI_SOURCE_LENGTH) { dprintf( " Non Maskable Interrupt source has length 0x%x instead of 0x%x\n", ReturnChar(iso, "acpi!_IO_NMISOURCE", "Length"), IO_NMI_SOURCE_LENGTH ); break; } hasMPSFlags = TRUE; flags = isoFlags; } else if (ReturnChar(iso,"hal!_LOCAL_NMISOURCE","Type") == LOCAL_NMI_SOURCE) { buffer += ReturnChar(iso, "hal!_LOCAL_NMISOURCE", "Length"); GetFieldValue(iso, "hal!_LOCAL_NMISOURCE", "Flags", isoFlags); dprintf( " Non Maskable Interrupt Source - local to processor\n" " Flags: 0x%04x\n" " Processor: 0x%02x %s\n" " LINTIN: 0x%02x\n", isoFlags, ReturnChar(iso, "hal!_LOCAL_NMISOURCE", "ProcessorID"), ReturnChar(iso,"hal!_LOCAL_NMISOURCE","ProcessorID") == 0xff ? "(all)" : "", ReturnChar(iso, "hal!_LOCAL_NMISOURCE", "LINTIN") ); if (ReturnChar(iso,"hal!_LOCAL_NMISOURCE","Length") != LOCAL_NMI_SOURCE_LENGTH) { dprintf( " Non Maskable Interrupt source has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_LOCAL_NMISOURCE", "Length"), IO_NMI_SOURCE_LENGTH ); break; } hasMPSFlags = TRUE; flags = isoFlags; } else if (ReturnChar(iso, "hal!_PROCLOCALSAPIC", "Type") == LOCAL_SAPIC) { buffer += ReturnChar(iso, "hal!_PROCLOCALSAPIC", "Length"); dprintf( " Processor Local SAPIC\n" " ACPI Processor ID: 0x%02x\n" " APIC ID: 0x%02x\n" " APIC EID: 0x%02x\n" " Flags: 0x%08lx\n", ReturnChar(iso, "hal!_PROCLOCALSAPIC", "ACPIProcessorID"), ReturnChar(iso, "hal!_PROCLOCALSAPIC", "APICID"), ReturnChar(iso, "hal!_PROCLOCALSAPIC", "APICEID"), ReturnULONG(iso, "hal!_PROCLOCALSAPIC", "Flags") ); if (ReturnChar(iso, "hal!_PROCLOCALSAPIC", "Length") != PROCESSOR_LOCAL_SAPIC_LENGTH) { dprintf( " Processor Local SAPIC has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_PROCLOCALSAPIC", "Length"), PROCESSOR_LOCAL_SAPIC_LENGTH ); break; } } else if (ReturnChar(iso, "hal!_IOSAPIC", "Type") == IO_SAPIC) { buffer += ReturnChar(iso, "hal!_IOSAPIC", "Length"); dprintf( " IO SApic\n" " IO SAPIC ADDRESS: 0x%016I64x\n" " System Vector Base: 0x%08lx\n", ReturnULONG64(iso, "hal!_IOSAPIC", "IOSAPICAddress"), ReturnULONG(iso, "hal!_IOSAPIC", "SystemVectorBase") ); if (ReturnChar(iso, "hal!_IOSAPIC", "Length") != IO_SAPIC_LENGTH) { dprintf( " IO SApic has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_IOSAPIC", "Length"), IO_SAPIC_LENGTH ); break; } } else if (ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "Type") == PLATFORM_INTERRUPT_SOURCE) { UCHAR InterruptType = ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "InterruptType"); buffer += ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "Length"); dprintf( " Platform Interrupt Source\n" " Flags: 0x%04x\n" " Interrupt Type: %s\n" " APICID: 0x%02x\n" " APICEID: 0x%02x\n" " IOSAPICVector: 0x%02x\n" " GlobalVector: 0x%08x\n", ReturnUSHORT(iso, "hal!_PLATFORM_INTERRUPT", "Flags"), InterruptType == PLATFORM_INT_PMI ? "PMI" : (InterruptType == PLATFORM_INT_INIT ? "INIT" : (InterruptType == PLATFORM_INT_CPE ? "CPE" : "UNKNOWN")), ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "APICID"), ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "APICEID"), ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "IOSAPICVector"), ReturnULONG(iso, "hal!_PLATFORM_INTERRUPT", "GlobalVector") ); if (ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "Length") != PLATFORM_INTERRUPT_SOURCE_LENGTH) { dprintf( " Platform Interrupt Source has length 0x%x instead of 0x%x\n", ReturnChar(iso, "hal!_PLATFORM_INTERRUPT", "Length"), PLATFORM_INTERRUPT_SOURCE_LENGTH ); break; } } else { dprintf(" UNKNOWN RECORD (%p)\n", iso); dprintf(" Type: 0x%08x\n", ReturnChar(iso,"hal!_IOAPIC","Type")); dprintf(" Length: 0x%08x\n", ReturnChar(iso,"hal!_IOAPIC","Length")); // // Dont spin forever if we encounter an known with zero length // if ((ReturnChar(iso,"hal!_IOAPIC","Length")) == 0) { break; } buffer += ReturnChar(iso,"hal!_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; } } } return; } DECLARE_API( mapic ) { if (args != NULL) { AcpiMapicAddress = GetExpression( args ); } if (AcpiMapicAddress == 0) { BOOL status; ULONG64 address; status = GetUlongPtr( "ACPI!AcpiInformation", &address ); if (status == TRUE) { status = GetFieldValue(address,"ACPI!_ACPIInformation","MultipleApicTable",AcpiMapicAddress); } } if (AcpiMapicAddress == 0) { dprintf("mapic \n"); return E_INVALIDARG; } dumpMAPIC( AcpiMapicAddress ); return S_OK; } VOID dumpGBLEntry( IN ULONG64 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; UCHAR tableId[7]; UCHAR entryId[20]; // // Read the header for the table // InitTypeRead( Address, hal!_DESCRIPTION_HEADER); // // Don't print out a table unless its the FACP or we are being verbose // if (!(Verbose & VERBOSE_2) && ReadField(Signature) != FADT_SIGNATURE) { return; } // // Initialize the table id field // memset( tableId, 0, 7 ); tableId[0] = '\"'; memcpy( &tableId[1], ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "Signature", sizeof(ULONG), FALSE), sizeof(ULONG) ); strcat( tableId, "\"" ); // // Get the entry ready for the OEM Id // memset( entryId, 0, 20 ); entryId[0] = '\"'; memcpy( &entryId[1], ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "OEMID", 6, FALSE), 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], ReadPhysVirField(Address, "hal!_DESCRIPTION_HEADER", "OEMTableID", 8, FALSE), 8 ); strcat( entryId, "\""); dprintf("AcpiOemTableId=%s,%s\n", tableId, entryId ); // // Get the entry ready for the OEM Revision // dprintf("AcpiOemRevision=\">=\",%s,%x\n", tableId, (ULONG)ReadField(OEMRevision) ); // // Get the entry ready for the ACPI revision // if (ReadField(Revision) != 1) { dprintf("AcpiRevision=\">=\",%s,%x\n", tableId, (UCHAR)ReadField(Revision) ); } // // Get the entry ready for the ACPI Creator Revision // dprintf("AcpiCreatorRevision=\">=\",%s,%x\n", tableId, (ULONG)ReadField(CreatorRev) ); } 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 --*/ { BOOL status; ULONG64 dateAddress; PUCHAR tempPtr; ULONG i; ULONG numElements; ULONG returnLength; ULONG64 address; ULONG64 address2; ULONG addr; ULONG64 addroffset; // // 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 = ReadPointer(address2, &address); if (status == FALSE || !address) { dprintf("dumpGBL: No RsdtInformation present\n"); return; } // // Read the ACPInformation table, so that we know where the RSDT lives // address2 = GetExpression( "ACPI!AcpiInformation" ); if (!address2) { dprintf("dumpGBL: Could not find AcpiInformation\n"); return; } status = ReadPointer(address2, &address2); if (status == FALSE || !address2) { dprintf("dumpGBL: Could not read AcpiInformation\n"); return; } InitTypeRead( address2, ACPI!_ACPIInformation); // // Read in the header for the RSDT // address2 = ReadField(RootSystemDescTable); // // The number of elements in the table is the first entry // in the structure // //status = ReadMemory(address, &numElements, GetTypeSize("acpi!_ULONG"), &returnLength); status = ReadMemory(address, &numElements, sizeof(ULONG), &returnLength); //if (status == FALSE || returnLength != GetTypeSize("acpi!_ULONG") ) { 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; } // // 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 ); GetFieldOffset( "hal!_DESCRIPTION_HEADER", "OEMID", &addr); ReadMemory( (address2 + (ULONG64) addr), &Buffer, 6, &returnLength); tempPtr = Buffer; while (*tempPtr) { if (*tempPtr == ' ') { *tempPtr = '\0'; break; } tempPtr++; } GetFieldOffset( "hal!_DESCRIPTION_HEADER", "OEMTableID", &addr); ReadMemory( (address2 + (ULONG64) addr), tempPtr, 8, &returnLength); 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 all the tables that are loaded in the RSDT table // GetFieldOffset( "ACPI!_RSDTINFORMATION", "Tables", &addr); // Get Tables offset for (i = 0; i < numElements; i++) { addroffset = address + (ULONG64)addr + (ULONG64)(GetTypeSize("ACPI!RSDTELEMENT") * i); InitTypeRead(addroffset, ACPI!RSDTELEMENT); if (!(ReadField(Flags) & RSDTELEMENT_MAPPED) ) { continue; } dumpGBLEntry( ReadField(Address), Verbose ); } // // Dump the entry for the RSDT // dumpGBLEntry( address2, Verbose ); // // Add some whitespace // dprintf("\n"); // // Done // return; } DECLARE_API( gbl ) { ULONG verbose = VERBOSE_1; if (args != NULL) { if (!strcmp(args, "-v")) { verbose |= VERBOSE_2; } } dumpGBL( verbose ); return S_OK; } /*************************** INF Starts Here ********************************/ ULONG dumpFlags( IN ULONGLONG Value, IN PFLAG_RECORD FlagRecords, IN ULONG FlagRecordSize, IN ULONG IndentLevel, IN ULONG Flags ) /*++ Routine Description: This routine dumps the flags specified in Value according to the description passing into FlagRecords. The formating is affected by the flags field Arguments: Value - The values FlagRecord - What each bit in the flags means FlagRecordSize - How many flags there are IndentLevel - The base indent level Flags - How we will process the flags Return Value: ULONG - the number of characters printed. 0 if we printed nothing --*/ #define STATUS_PRINTED 0x00000001 #define STATUS_INDENTED 0x00000002 #define STATUS_NEED_COUNTING 0x00000004 #define STATUS_COUNTED 0x00000008 { PCHAR string; UCHAR indent[80]; ULONG column = IndentLevel; ULONG currentStatus = 0; ULONG fixedSize = 0; ULONG stringSize; ULONG tempCount; ULONG totalCount = 0; ULONG64 i, j, k; IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( indent, ' ', IndentLevel ); indent[IndentLevel] = '\0'; // // Do we need to make a table? // if ( (Flags & DUMP_FLAG_TABLE) && !(Flags & DUMP_FLAG_SINGLE_LINE) ) { currentStatus |= STATUS_NEED_COUNTING; } if ( (Flags & DUMP_FLAG_ALREADY_INDENTED) ) { currentStatus |= STATUS_INDENTED; } // // loop over all the steps that we need to do // while (1) { for (i = 0; i < 32; i++) { k = (1 << i); for (j = 0; j < FlagRecordSize; j++) { if (!(FlagRecords[j].Bit & Value) ) { // // Are we looking at the correct bit? // if (!(FlagRecords[j].Bit & k) ) { continue; } // // Yes, we are, so pick the not-present values // if ( (Flags & DUMP_FLAG_LONG_NAME && FlagRecords[j].NotLongName == NULL) || (Flags & DUMP_FLAG_SHORT_NAME && FlagRecords[j].NotShortName == NULL) ) { continue; } if ( (Flags & DUMP_FLAG_LONG_NAME) ) { string = FlagRecords[j].NotLongName; } else if ( (Flags & DUMP_FLAG_SHORT_NAME) ) { string = FlagRecords[j].NotShortName; } } else { // // Are we looking at the correct bit? // if (!(FlagRecords[j].Bit & k) ) { continue; } // // Yes, we are, so pick the not-present values // if ( (Flags & DUMP_FLAG_LONG_NAME && FlagRecords[j].LongName == NULL) || (Flags & DUMP_FLAG_SHORT_NAME && FlagRecords[j].ShortName == NULL) ) { continue; } if ( (Flags & DUMP_FLAG_LONG_NAME) ) { string = FlagRecords[j].LongName; } else if ( (Flags & DUMP_FLAG_SHORT_NAME) ) { string = FlagRecords[j].ShortName; } } if (currentStatus & STATUS_NEED_COUNTING) { stringSize = strlen( string ) + 1; if (Flags & DUMP_FLAG_SHOW_BIT) { stringSize += (4 + ( (ULONG) i / 4)); if ( (i % 4) != 0) { stringSize++; } } if (stringSize > fixedSize) { fixedSize = stringSize; } continue; } if (currentStatus & STATUS_COUNTED) { stringSize = fixedSize; } else { stringSize = strlen( string ) + 1; if (Flags & DUMP_FLAG_SHOW_BIT) { stringSize += (4 + ( (ULONG) i / 4)); if ( (i % 4) != 0) { stringSize++; } } } if (!(Flags & DUMP_FLAG_SINGLE_LINE) ) { if ( (stringSize + column) > 79 ) { dprintf("\n%n", &tempCount); currentStatus &= ~STATUS_INDENTED; totalCount += tempCount; column = 0; } } if (!(Flags & DUMP_FLAG_NO_INDENT) ) { if (!(currentStatus & STATUS_INDENTED) ) { dprintf("%s%n", indent, &tempCount); currentStatus |= STATUS_INDENTED; totalCount += tempCount; column += IndentLevel; } } if ( (Flags & DUMP_FLAG_SHOW_BIT) ) { dprintf("%I64x - %n", k, &tempCount); tempCount++; // to account for the fact that we dump // another space at the end of the string totalCount += tempCount; column += tempCount; } else { tempCount = 0; } // // Actually print the string // dprintf( "%.*s %n", (stringSize - tempCount), string, &tempCount ); if (Flags & DUMP_FLAG_SHOW_BIT) { dprintf(" "); } totalCount += tempCount; column += tempCount; } } // // Change states // if (currentStatus & STATUS_NEED_COUNTING) { currentStatus &= ~STATUS_NEED_COUNTING; currentStatus |= STATUS_COUNTED; continue; } if (!(Flags & DUMP_FLAG_NO_EOL) && totalCount != 0) { dprintf("\n"); totalCount++; } // // Done // break; } return totalCount; } VOID dumpPM1ControlRegister( IN ULONG Value, IN ULONG IndentLevel ) { // // Dump the PM1 Control Flags // dumpFlags( (Value & 0xFF), PM1ControlFlags, sizeof(PM1ControlFlags) / sizeof(FLAG_RECORD), IndentLevel, (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE) ); } VOID dumpPM1StatusRegister( IN ULONG Value, IN ULONG IndentLevel ) { // // Dump the PM1 Status Flags // dumpFlags( (Value & 0xFFFF), PM1StatusFlags, (sizeof(PM1StatusFlags) / sizeof(FLAG_RECORD)), IndentLevel, (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE) ); // // Switch to the PM1 Enable Flags // Value >>= 16; // // Dump the PM1 Enable Flags // dumpFlags( (Value & 0xFFFF), PM1EnableFlags, (sizeof(PM1EnableFlags) / sizeof(FLAG_RECORD)), IndentLevel, (DUMP_FLAG_LONG_NAME | DUMP_FLAG_SHOW_BIT | DUMP_FLAG_TABLE) ); } VOID dumpAcpiInformation( VOID ) { BOOL status; ULONG64 address; ULONG returnLength; ULONG size; ULONG value; ULONG addr; ULONG i; ULONG64 getValue; ULONG64 getValue2; status = GetUlongPtr( "ACPI!AcpiInformation", &address ); if (status == FALSE) { dprintf("dumpAcpiInformation: Could not read ACPI!AcpiInformation\n"); return; } InitTypeRead(address, ACPI!_ACPIInformation); dprintf("ACPIInformation (%p)\n", address); dprintf( " RSDT - %p\n", ReadField(RootSystemDescTable) ); dprintf( " FADT - %p\n", ReadField(FixedACPIDescTable) ); dprintf( " FACS - %p\n", ReadField(FirmwareACPIControlStructure) ); dprintf( " DSDT - %p\n", ReadField(DiffSystemDescTable) ); dprintf( " GlobalLock - %p\n", ReadField(GlobalLock) ); dprintf( " GlobalLockQueue - F - %p B - %p\n", ReadField(GlobalLockQueue.Flink), ReadField(GlobalLockQueue.Blink) ); dprintf( " GlobalLockQueueLock - %p\n", ReadField(GlobalLockQueueLock) ); dprintf( " GlobalLockOwnerContext - %p\n", ReadField(GlobalLockOwnerContext) ); dprintf( " GlobalLockOwnerDepth - %p\n", ReadField(GlobalLockOwnerDepth) ); dprintf( " ACPIOnly - %s\n", (ReadField(ACPIOnly) ? "TRUE" : "FALSE" ) ); dprintf( " PM1a_BLK - %p", ReadField(PM1a_BLK) ); if (ReadField(PM1a_BLK)) { size = 4; value = 0; ReadIoSpace64( (ULONG) ReadField(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 - %p", ReadField(PM1b_BLK) ); if (ReadField(PM1b_BLK)) { size = 4; value = 0; ReadIoSpace64( (ULONG) ReadField(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 - %p", ReadField(PM1a_CTRL_BLK) ); if (ReadField(PM1a_CTRL_BLK)) { size = 2; value = 0; ReadIoSpace64( (ULONG) ReadField(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 - %p", ReadField(PM1b_CTRL_BLK) ); if (ReadField(PM1b_CTRL_BLK)) { size = 2; value = 0; ReadIoSpace64( (ULONG) ReadField(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 - %p", ReadField(PM2_CTRL_BLK) ); if (ReadField(PM2_CTRL_BLK)) { size = 1; value = 0; ReadIoSpace64( (ULONG) ReadField(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 - %p", ReadField(PM_TMR) ); if (ReadField(PM_TMR)) { size = 4; value = 0; ReadIoSpace64( (ULONG) ReadField(PM_TMR), &value, &size ); if (size) { dprintf(" (%08lx)\n", value ); } else { dprintf(" (N/A)\n"); } } else { dprintf(" (N/A)\n"); } dprintf( " GP0_BLK - %p", ReadField(GP0_BLK) ); if (ReadField(GP0_BLK)) { for(i = 0; i < ReadField(Gpe0Size); i++) { size = 1; value = 0; ReadIoSpace64( (ULONG) ReadField(GP0_BLK) + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP0_ENABLE - %p", ReadField(GP0_ENABLE) ); if (ReadField(GP0_ENABLE)) { for(i = 0; i < ReadField(Gpe0Size); i++) { size = 1; value = 0; ReadIoSpace64( (ULONG) ReadField(GP0_ENABLE) + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP0_LEN - %p\n", ReadField(GP0_LEN) ); dprintf( " GP0_SIZE - %p\n", ReadField(Gpe0Size) ); dprintf( " GP1_BLK - %p", ReadField(GP1_BLK) ); if (ReadField(GP1_BLK)) { for(i = 0; i < ReadField(Gpe0Size); i++) { size = 1; value = 0; ReadIoSpace64( (ULONG) ReadField(GP1_BLK) + i, &value, &size ); if (size) { dprintf(" (%02x)", value ); } else { dprintf(" (N/A)" ); } } dprintf("\n"); } else { dprintf(" (N/A)\n"); } dprintf( " GP1_ENABLE - %p", ReadField(GP1_ENABLE) ); if (ReadField(GP1_ENABLE)) { for(i = 0; i < ReadField(Gpe0Size); i++) { size = 1; value = 0; ReadIoSpace64( (ULONG) ReadField(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", ReadField(GP1_LEN) ); dprintf( " GP1_SIZE - %x\n", ReadField(Gpe1Size) ); dprintf( " GP1_BASE_INDEX - %x\n", ReadField(GP1_Base_Index) ); dprintf( " GPE_SIZE - %x\n", ReadField(GpeSize) ); dprintf( " PM1_EN_BITS - %04x\n", ReadField(pm1_en_bits) ); dumpPM1StatusRegister( ( (ULONG) ReadField(pm1_en_bits) << 16), 5 ); dprintf( " PM1_WAKE_MASK - %04x\n", ReadField(pm1_wake_mask) ); dumpPM1StatusRegister( ( (ULONG) ReadField(acpiInformation.pm1_wake_mask) << 16), 5 ); dprintf( " C2_LATENCY - %x\n", ReadField(c2_latency) ); dprintf( " C3_LATENCY - %x\n", ReadField(c3_latency) ); dprintf( " ACPI_FLAGS - %x\n", ReadField(ACPI_Flags) ); if (ReadField(ACPI_Flags) & C2_SUPPORTED) { dprintf(" %2d - C2_SUPPORTED\n", C2_SUPPORTED_BIT); } if (ReadField(ACPI_Flags) & C3_SUPPORTED) { dprintf(" %2d - C3_SUPPORTED\n", C3_SUPPORTED_BIT); } if (ReadField(ACPI_Flags) & C3_PREFERRED) { dprintf(" %2d - C3_PREFERRED\n", C3_PREFERRED_BIT); } dprintf( " ACPI_CAPABILITIES - %x\n", ReadField(ACPI_Capabilities) ); if (ReadField(ACPI_Capabilities) & CSTATE_C1) { dprintf(" %2d - CSTATE_C1\n", CSTATE_C1_BIT ); } if (ReadField(ACPI_Capabilities) & CSTATE_C2) { dprintf(" %2d - CSTATE_C2\n", CSTATE_C2_BIT ); } if (ReadField(ACPI_Capabilities) & CSTATE_C3) { dprintf(" %2d - CSTATE_C3\n", CSTATE_C3_BIT ); } } DECLARE_API( acpiinf ) { dumpAcpiInformation( ); return S_OK; } VOID dumpObject( IN ULONG64 Object, IN ULONG Verbose, IN ULONG IndentLevel ) /*++ Routine Description: This dumps an Objdata so that it can be understand --- great for debugging some of the AML code Arguments: Object - Address of OBJDATA structure Return Value: None --*/ { ULONG64 s; NTSTATUS status; UCHAR buffer[2048]; UCHAR indent[80]; ULONG64 max; ULONG64 pbDataBuffoffset = 0; ULONG64 offset = 0; UCHAR StrBuffer[2048]; // // Init the buffers // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( indent, ' ', IndentLevel ); indent[IndentLevel] = '\0'; // // Get the offset to pbDataBuff // InitTypeRead (Object, acpi!_ObjData); pbDataBuffoffset = ReadField (pbDataBuff); dprintf("%sObject Data - %016I64x Type - ", indent, Object); // // First step is to read whatever the buffer points to, if it // points to something // switch( ReadField (dwDataType) ) { case OBJTYPE_INTDATA: dprintf( "%02I64x