You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4017 lines
109 KiB
4017 lines
109 KiB
/*++
|
|
|
|
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)
|
|
|
|
#define SEALED_CASE_CAP_BIT 11
|
|
#define SEALED_CASE_CAP (1 << SEALED_CASE_CAP_BIT)
|
|
|
|
#define HEADLESS_CAP_BIT 12
|
|
#define HEADLESS_CAP (1 << HEADLESS_CAP_BIT)
|
|
|
|
#define CPU_SW_SLP_BIT 13
|
|
#define CPU_SW_SLP (1 << CPU_SW_SLP_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"
|
|
#define SRAT_SIGNATURE 0x54415253 // "SRAT"
|
|
|
|
#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
|
|
|
|
//
|
|
// SRAT Stuff
|
|
//
|
|
|
|
#define SRAT_ENTRY_TYPE_PROCESSOR 0
|
|
#define SRAT_ENTRY_TYPE_MEMORY 1
|
|
|
|
// 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;
|
|
}
|
|
|
|
ULONG64
|
|
GetPointerFromAddressPhysicalOrVirtual(
|
|
IN ULONG64 Address,
|
|
IN BOOL Virtual
|
|
)
|
|
{
|
|
ULONG answer32 = 0;
|
|
ULONG64 answer64 = 0;
|
|
ULONG size;
|
|
ULONG returnLength;
|
|
BOOL status;
|
|
|
|
size = GetTypeSize("hal!ULONG_PTR");
|
|
|
|
if (size == 4) {
|
|
status = ReadPhysicalOrVirtual(Address,
|
|
&answer32,
|
|
size,
|
|
&returnLength,
|
|
Virtual);
|
|
answer64 = (ULONG64) answer32;
|
|
} else {
|
|
status = ReadPhysicalOrVirtual(Address,
|
|
&answer64,
|
|
size,
|
|
&returnLength,
|
|
Virtual);
|
|
}
|
|
|
|
if ((status == FALSE) || (returnLength != size)) {
|
|
return 0;
|
|
}
|
|
|
|
return answer64;
|
|
}
|
|
|
|
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 );
|
|
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
|
|
);
|
|
|
|
}
|
|
|
|
if (flags & DCK_CAP_BIT) {
|
|
dprintf(" The machine has the docking capable attribute.\n");
|
|
}
|
|
|
|
if (flags & SEALED_CASE_CAP_BIT) {
|
|
dprintf(" The machine has the sealed case system attribute.\n");
|
|
}
|
|
|
|
if (flags & HEADLESS_CAP_BIT) {
|
|
dprintf(" The machine is reported has the sealed case system attribute.\n");
|
|
}
|
|
|
|
if (flags & CPU_SW_SLP_BIT) {
|
|
dprintf(" The machine has the CPU_SW_SLP_BIT set.\n");
|
|
}
|
|
|
|
}
|
|
|
|
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 <address>\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 <address>\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
|
|
UCHAR
|
|
ReturnUCHAR(
|
|
IN ULONG64 Address,
|
|
IN PUCHAR StructName,
|
|
IN PUCHAR FieldName
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Return char using GetFieldValue
|
|
--*/
|
|
{
|
|
UCHAR 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 (ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "Type") == PROCESSOR_LOCAL_APIC) {
|
|
|
|
buffer += ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "Length");
|
|
|
|
dprintf(
|
|
" Processor Local Apic\n"
|
|
" ACPI Processor ID: 0x%02x\n"
|
|
" APIC ID: 0x%02x\n"
|
|
" Flags: 0x%08lx\n",
|
|
ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "ACPIProcessorID"),
|
|
ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "APICID"),
|
|
ReturnULONG(iso, "acpi!_PROCLOCALAPIC", "Flags")
|
|
);
|
|
if (ReturnULONG(iso, "acpi!_PROCLOCALAPIC", "Flags") & PLAF_ENABLED) {
|
|
dprintf(" Processor is Enabled\n");
|
|
}
|
|
if (ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "Length") != PROCESSOR_LOCAL_APIC_LENGTH) {
|
|
dprintf(
|
|
" Local Apic has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "acpi!_PROCLOCALAPIC", "Length"),
|
|
PROCESSOR_LOCAL_APIC_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
} else if (ReturnUCHAR(iso, "hal!_IOAPIC", "Type") == IO_APIC) {
|
|
|
|
buffer += ReturnUCHAR(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",
|
|
ReturnUCHAR(iso, "hal!_IOAPIC", "IOAPICID"),
|
|
ReturnULONG(iso, "hal!_IOAPIC", "IOAPICAddress"),
|
|
ReturnULONG(iso, "hal!_IOAPIC", "SystemVectorBase")
|
|
);
|
|
if (ReturnUCHAR(iso, "hal!_IOAPIC", "Length") != IO_APIC_LENGTH) {
|
|
dprintf(
|
|
" IO Apic has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_IOAPIC", "Length"),
|
|
IO_APIC_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
} else if (ReturnUCHAR(iso,"hal!_ISA_VECTOR","Type") == ISA_VECTOR_OVERRIDE) {
|
|
buffer += ReturnUCHAR(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",
|
|
ReturnUCHAR(iso, "hal!_ISA_VECTOR", "Bus"),
|
|
ReturnUCHAR(iso, "hal!_ISA_VECTOR", "Source"),
|
|
ReturnULONG(iso, "hal!_ISA_VECTOR", "GlobalSystemInterruptVector"),
|
|
isoFlags
|
|
);
|
|
if (ReturnUCHAR(iso,"hal!_ISA_VECTOR","Length") != ISA_VECTOR_OVERRIDE_LENGTH) {
|
|
dprintf(
|
|
" Interrupt Source Override has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_ISA_VECTOR", "Length"),
|
|
ISA_VECTOR_OVERRIDE_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
hasMPSFlags = TRUE;
|
|
flags = isoFlags;
|
|
} else if (ReturnUCHAR(iso,"acpi!_IO_NMISOURCE","Type") == IO_NMI_SOURCE) {
|
|
buffer += ReturnUCHAR(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 (ReturnUCHAR(iso,"acpi!_IO_NMISOURCE","Length") != IO_NMI_SOURCE_LENGTH) {
|
|
dprintf(
|
|
" Non Maskable Interrupt source has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "acpi!_IO_NMISOURCE", "Length"),
|
|
IO_NMI_SOURCE_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
hasMPSFlags = TRUE;
|
|
flags = isoFlags;
|
|
} else if (ReturnUCHAR(iso,"hal!_LOCAL_NMISOURCE","Type") == LOCAL_NMI_SOURCE) {
|
|
buffer += ReturnUCHAR(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,
|
|
ReturnUCHAR(iso, "hal!_LOCAL_NMISOURCE", "ProcessorID"),
|
|
ReturnUCHAR(iso,"hal!_LOCAL_NMISOURCE","ProcessorID") == 0xff ? "(all)" : "",
|
|
ReturnUCHAR(iso, "hal!_LOCAL_NMISOURCE", "LINTIN")
|
|
);
|
|
if (ReturnUCHAR(iso,"hal!_LOCAL_NMISOURCE","Length") != LOCAL_NMI_SOURCE_LENGTH) {
|
|
dprintf(
|
|
" Non Maskable Interrupt source has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_LOCAL_NMISOURCE", "Length"),
|
|
IO_NMI_SOURCE_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
|
|
hasMPSFlags = TRUE;
|
|
flags = isoFlags;
|
|
} else if (ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "Type") == LOCAL_SAPIC) {
|
|
buffer += ReturnUCHAR(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",
|
|
ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "ACPIProcessorID"),
|
|
ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "APICID"),
|
|
ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "APICEID"),
|
|
ReturnULONG(iso, "hal!_PROCLOCALSAPIC", "Flags")
|
|
);
|
|
if (ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "Length") != PROCESSOR_LOCAL_SAPIC_LENGTH) {
|
|
dprintf(
|
|
" Processor Local SAPIC has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_PROCLOCALSAPIC", "Length"),
|
|
PROCESSOR_LOCAL_SAPIC_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
} else if (ReturnUCHAR(iso, "hal!_IOSAPIC", "Type") == IO_SAPIC) {
|
|
buffer += ReturnUCHAR(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 (ReturnUCHAR(iso, "hal!_IOSAPIC", "Length") != IO_SAPIC_LENGTH) {
|
|
dprintf(
|
|
" IO SApic has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_IOSAPIC", "Length"),
|
|
IO_SAPIC_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
} else if (ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "Type") == PLATFORM_INTERRUPT_SOURCE) {
|
|
|
|
UCHAR InterruptType = ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "InterruptType");
|
|
|
|
buffer += ReturnUCHAR(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")),
|
|
ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "APICID"),
|
|
ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "APICEID"),
|
|
ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "IOSAPICVector"),
|
|
ReturnULONG(iso, "hal!_PLATFORM_INTERRUPT", "GlobalVector")
|
|
);
|
|
if (ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "Length") != PLATFORM_INTERRUPT_SOURCE_LENGTH) {
|
|
dprintf(
|
|
" Platform Interrupt Source has length 0x%x instead of 0x%x\n",
|
|
ReturnUCHAR(iso, "hal!_PLATFORM_INTERRUPT", "Length"),
|
|
PLATFORM_INTERRUPT_SOURCE_LENGTH
|
|
);
|
|
break;
|
|
}
|
|
} else {
|
|
dprintf(" UNKNOWN RECORD (%p)\n", iso);
|
|
dprintf(" Type: 0x%08x\n", ReturnUCHAR(iso,"hal!_IOAPIC","Type"));
|
|
dprintf(" Length: 0x%08x\n", ReturnUCHAR(iso,"hal!_IOAPIC","Length"));
|
|
|
|
//
|
|
// Dont spin forever if we encounter an known with zero length
|
|
//
|
|
if ((ReturnUCHAR(iso,"hal!_IOAPIC","Length")) == 0) {
|
|
break;
|
|
}
|
|
|
|
buffer += ReturnUCHAR(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 <address>\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dumpMAPIC( AcpiMapicAddress );
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
VOID
|
|
dumpSRAT(
|
|
IN ULONG64 Address,
|
|
IN BOOLEAN Physical
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This dumps the static resource affinity table
|
|
|
|
Arguments:
|
|
|
|
Address -- Address of the table
|
|
|
|
Physical -- TRUE indicates a physical address, FALSE indicates a
|
|
virtual address
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
BOOL status;
|
|
ULONG sratLength;
|
|
ULONG64 sratEnd;
|
|
ULONG64 current;
|
|
|
|
//
|
|
// First check to see if we find the correct things
|
|
//
|
|
dprintf("SRAT - ");
|
|
|
|
if (Physical) {
|
|
InitTypeReadPhysical( Address, hal!_ACPI_SRAT);
|
|
} else {
|
|
InitTypeRead( Address, hal!_ACPI_SRAT);
|
|
}
|
|
|
|
if (ReadField(Header.Signature) != SRAT_SIGNATURE) {
|
|
dprintf(
|
|
"dumpSRAT: Invalid Signature 0x%08lx != SRAT_SIGNATURE (%x)\n",
|
|
(ULONG) ReadField(Signature),
|
|
SRAT_SIGNATURE
|
|
);
|
|
return;
|
|
}
|
|
|
|
dumpHeader( Address, TRUE, Physical );
|
|
current = Address + GetTypeSize("hal!_ACPI_SRAT");
|
|
dprintf("SRAT - BODY - %016I64x\n", current);
|
|
dprintf(" Table Revision: %d\n", (ULONG) ReadField(TableRevision));
|
|
|
|
sratEnd = Address + (ULONG)ReadField(Length);
|
|
|
|
while (current < sratEnd) {
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
if (Physical) {
|
|
InitTypeReadPhysical( current, hal!_ACPI_SRAT_ENTRY);
|
|
} else {
|
|
InitTypeRead( current, hal!_ACPI_SRAT_ENTRY);
|
|
}
|
|
|
|
dprintf("ENTRY:\n\tType: 0x%02X\n\tLength: 0x%02X\n\tProximityId: 0x%02X\n",
|
|
(ULONG) ReadField(Type),
|
|
(ULONG) ReadField(Length),
|
|
(ULONG) ReadField(ProximityDomain));
|
|
|
|
switch (ReadField(Type)) {
|
|
|
|
case SRAT_ENTRY_TYPE_PROCESSOR:
|
|
dprintf("\tProcessor:\n");
|
|
dprintf("\t\tEnabled: %s\n",
|
|
ReadField(ApicAffinity.Flags.Enabled) ? "TRUE" : "FALSE");
|
|
dprintf("\t\tAPIC ID: 0x%02X",
|
|
(ULONG) ReadField(ApicAffinity.ApicId));
|
|
if (TargetMachine == IMAGE_FILE_MACHINE_IA64) {
|
|
dprintf(" SAPIC EID 0x%02X\n",
|
|
(ULONG) ReadField(ApicAffinity.SApicEid));
|
|
} else {
|
|
dprintf("\n");
|
|
}
|
|
break;
|
|
case SRAT_ENTRY_TYPE_MEMORY:
|
|
dprintf("\tMemory:\n");
|
|
dprintf("\t\tEnabled: %s\n\t\tHotPlug: %s\n",
|
|
ReadField(MemoryAffinity.Flags.Enabled) ? "TRUE" : "FALSE",
|
|
ReadField(MemoryAffinity.Flags.HotPlug) ? "TRUE" : "FALSE");
|
|
dprintf("\t\tBase: %016I64X\tLength: %016I64X\n",
|
|
ReadField(MemoryAffinity.Base),
|
|
ReadField(MemoryAffinity.Length));
|
|
dprintf("\t\t (%016I64X - %016I64X)\n",
|
|
ReadField(MemoryAffinity.Base),
|
|
ReadField(MemoryAffinity.Base) +
|
|
ReadField(MemoryAffinity.Length) - 1);
|
|
break;
|
|
default:
|
|
dprintf("\tUNKNOWN SRAT ENTRY TYPE\n");
|
|
}
|
|
|
|
current += ReadField(Length);
|
|
}
|
|
}
|
|
|
|
DECLARE_API( srat )
|
|
{
|
|
ULONG64 acpiSRATAddress = 0;
|
|
BOOLEAN Physical = FALSE;
|
|
|
|
if (args != NULL) {
|
|
|
|
acpiSRATAddress = GetExpression( args );
|
|
Physical = TRUE;
|
|
}
|
|
|
|
if (acpiSRATAddress == 0) {
|
|
|
|
BOOL status;
|
|
ULONG64 address;
|
|
|
|
status = GetUlongPtr("hal!HalpAcpiSrat", &acpiSRATAddress );
|
|
if ((status == TRUE) && acpiSRATAddress) {
|
|
dprintf("Retrieved srat address from HAL NUMA code\n");
|
|
Physical = FALSE;
|
|
}
|
|
}
|
|
|
|
if (acpiSRATAddress == 0) {
|
|
dprintf("srat [<physical address>]\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dumpSRAT(acpiSRATAddress, Physical);
|
|
return S_OK;
|
|
}
|
|
|
|
DECLARE_API(numa_hal)
|
|
{
|
|
ULONG64 numaConfig;
|
|
ULONG64 memoryRanges;
|
|
ULONG64 ushortPtr;
|
|
ULONG64 ucharPtr;
|
|
ULONG64 range, lastRange;
|
|
ULONG64 endMarker;
|
|
ULONG offset;
|
|
ULONG numaNodeCount;
|
|
ULONG processorCount;
|
|
ULONG i;
|
|
ULONG returnLength;
|
|
USHORT apicId;
|
|
UCHAR proximityId;
|
|
BOOL status;
|
|
BOOL virtual;
|
|
|
|
status = GetUlongPtr("hal!HalpNumaConfig", &numaConfig );
|
|
if (status == FALSE) {
|
|
dprintf("The target's HAL does not support NUMA\n");
|
|
return S_OK;
|
|
}
|
|
|
|
if (numaConfig == 0) {
|
|
dprintf("The target is either not a NUMA machine or has not\n");
|
|
dprintf("proceeded far enough for the HAL to build the HAL's\n");
|
|
dprintf("NUMA datastructures\n");
|
|
return S_OK;
|
|
}
|
|
|
|
endMarker = (GetTypeSize("hal!ULONG_PTR") == 4) ?
|
|
(ULONG64) ~0UL : ~0I64;
|
|
|
|
if (TargetMachine != IMAGE_FILE_MACHINE_IA64) {
|
|
InitTypeRead( numaConfig, hal!_STATIC_NUMA_CONFIG);
|
|
virtual = TRUE;
|
|
} else {
|
|
InitTypeReadPhysical( numaConfig, hal!_STATIC_NUMA_CONFIG);
|
|
virtual = FALSE;
|
|
}
|
|
|
|
numaNodeCount = (UCHAR) ReadField(NodeCount);
|
|
processorCount = (UCHAR) ReadField(ProcessorCount);
|
|
|
|
dprintf("HAL NUMA Summary\n----------------\n");
|
|
|
|
dprintf(" Node Count : %d\n", (ULONG) numaNodeCount);
|
|
dprintf(" Processor Count : %d\n", (ULONG) processorCount);
|
|
|
|
GetFieldOffset( "hal!_STATIC_NUMA_CONFIG", "ProximityId", &offset);
|
|
ucharPtr = numaConfig + offset;
|
|
|
|
dprintf("\n Node ProximityId\n ----------------\n");
|
|
for (i = 0; i < numaNodeCount; i++) {
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
status = ReadPhysicalOrVirtual(ucharPtr + GetTypeSize("hal!UCHAR") * i,
|
|
&proximityId,
|
|
sizeof(UCHAR),
|
|
&returnLength,
|
|
virtual);
|
|
if ((status == FALSE) || (returnLength != sizeof(UCHAR))) {
|
|
dprintf("numa_hal: unable to retrieve HAL state\n");
|
|
return S_OK;
|
|
}
|
|
dprintf(" 0x%02X 0x%02X\n",
|
|
(ULONG) i,
|
|
(ULONG) proximityId);
|
|
}
|
|
|
|
GetFieldOffset( "hal!_STATIC_NUMA_CONFIG", "ProcessorApicId", &offset);
|
|
ushortPtr = numaConfig + offset;
|
|
|
|
GetFieldOffset( "hal!_STATIC_NUMA_CONFIG", "ProcessorProximity", &offset);
|
|
ucharPtr = numaConfig + offset;
|
|
|
|
dprintf("\n Proc Domain APIC Id\n ----------------------\n");
|
|
for (i = 0; i < processorCount; i++) {
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
status = ReadPhysicalOrVirtual(ushortPtr + GetTypeSize("hal!USHORT") * i,
|
|
&apicId,
|
|
sizeof(USHORT),
|
|
&returnLength,
|
|
virtual);
|
|
if ((status == FALSE) || (returnLength != sizeof(USHORT))) {
|
|
dprintf("numa_hal: unable to retrieve HAL state\n");
|
|
return S_OK;
|
|
}
|
|
status = ReadPhysicalOrVirtual(ucharPtr + GetTypeSize("hal!UCHAR") * i,
|
|
&proximityId,
|
|
sizeof(UCHAR),
|
|
&returnLength,
|
|
virtual);
|
|
if ((status == FALSE) || (returnLength != sizeof(UCHAR))) {
|
|
dprintf("numa_hal: unable to retrieve HAL state\n");
|
|
return S_OK;
|
|
}
|
|
dprintf(" 0x%02X 0x%02X 0x%04X\n",
|
|
(ULONG) i,
|
|
(ULONG) proximityId,
|
|
(ULONG) apicId);
|
|
}
|
|
|
|
(VOID) GetUlongPtr("hal!HalpNumaMemoryRanges", &memoryRanges);
|
|
(VOID) GetUlongPtr("hal!HalpNumaMemoryNode", &ucharPtr);
|
|
|
|
dprintf("\n Node Range\n ---------------\n");
|
|
for (;;) {
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
lastRange = GetPointerFromAddressPhysicalOrVirtual(memoryRanges,
|
|
virtual);
|
|
status = ReadPhysicalOrVirtual(ucharPtr,
|
|
&proximityId,
|
|
sizeof(UCHAR),
|
|
&returnLength,
|
|
virtual);
|
|
if ((status == FALSE) || (returnLength != sizeof(UCHAR))) {
|
|
dprintf("numa_hal: unable to retrieve HAL state\n");
|
|
return S_OK;
|
|
}
|
|
memoryRanges += GetTypeSize("hal!ULONG_PTR");
|
|
ucharPtr += GetTypeSize("hal!UCHAR");
|
|
range = GetPointerFromAddressPhysicalOrVirtual(memoryRanges,
|
|
virtual);
|
|
|
|
dprintf(" 0x%02X 0x%016I64X -> 0x%016I64X\n",
|
|
(ULONG) proximityId,
|
|
lastRange * PageSize,
|
|
range == endMarker ? ~0I64 : range * PageSize);
|
|
|
|
if (range == endMarker) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
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 = ((ULONG64) 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 <Integer> Value=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (uipDataValue)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_STRDATA:
|
|
|
|
if (ReadField (pbDataBuff) != 0) {
|
|
|
|
max = (ReadField (dwDataLen) > 2047 ? 2047 : ReadField (dwDataLen) );
|
|
|
|
}
|
|
buffer[max] = '\0';
|
|
|
|
ReadMemory (pbDataBuffoffset,
|
|
StrBuffer,
|
|
(ULONG) max,
|
|
NULL);
|
|
|
|
dprintf(
|
|
"%02I64x <String> String=%s\n",
|
|
ReadField (dwDataType),
|
|
StrBuffer
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFDATA:
|
|
dprintf(
|
|
"%02I64x <Buffer> Ptr=%016I64lx Length = %2I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (pbDataBuff),
|
|
ReadField (dwDataLen)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_PKGDATA: {
|
|
|
|
ULONG64 i = 0;
|
|
ULONG64 j = 0;
|
|
ULONG64 datatype = ReadField (dwDataType);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_PackageObj);
|
|
j = ReadField (dwcElements);
|
|
|
|
dprintf(
|
|
"%02I64x <Package> NumElements=%016I64x\n",
|
|
datatype,
|
|
j
|
|
);
|
|
|
|
if (Verbose & VERBOSE_OBJECT) {
|
|
|
|
for (; i < j; i++) {
|
|
|
|
GetFieldOffset ("acpi!_PackageObj", "adata", (ULONG*) &offset);
|
|
offset += (GetTypeSize ("acpi!_ObjData") * i);
|
|
|
|
dumpObject(offset + pbDataBuffoffset,
|
|
Verbose,
|
|
IndentLevel+ 2
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_FIELDUNIT: {
|
|
|
|
dprintf(
|
|
"%02I64x <Field Unit> ",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_FieldUnitObj);
|
|
|
|
dprintf(
|
|
"Parent=%016I64x Offset=%016I64x Start=%016I64x Num=%x Flags=%x\n",
|
|
ReadField (pnsFieldParent),
|
|
ReadField (FieldDesc.dwByteOffset),
|
|
ReadField (FieldDesc.dwStartBitPos),
|
|
ReadField (FieldDesc.dwNumBits),
|
|
ReadField (FieldDesc.dwFieldFlags)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_DEVICE:
|
|
dprintf(
|
|
"%02I64x <Device>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
case OBJTYPE_EVENT:
|
|
dprintf(
|
|
"%02I64x <Event> PKEvent=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (pbDataBuff)
|
|
);
|
|
break;
|
|
case OBJTYPE_METHOD: {
|
|
|
|
ULONG64 size;
|
|
|
|
offset = 0;
|
|
GetFieldOffset ("acpi!_MethodObj", "abCodeBuff", (ULONG *) &offset);
|
|
size = ReadField (dwDataLen) - GetTypeSize ("acpi!_MethodObj") + ANYSIZE_ARRAY;
|
|
|
|
dprintf(
|
|
"%02I64x <Method>",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_MethodObj);
|
|
|
|
dprintf(
|
|
"Flags=%016I64x Start=%016I64x Len=%016I64x\n",
|
|
ReadField (bMethodFlags),
|
|
offset + pbDataBuffoffset,
|
|
size
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_MUTEX:
|
|
|
|
dprintf(
|
|
"%02I64x <Mutex> Mutex=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (pbDataBuff)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_OPREGION: {
|
|
|
|
dprintf(
|
|
"%02I64x <Operational Region>",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_OpRegionObj);
|
|
|
|
dprintf(
|
|
"RegionSpace=%02x OffSet=%016I64x Len=%016I64x\n",
|
|
ReadField(bRegionSpace),
|
|
ReadField(uipOffset),
|
|
ReadField(dwLen)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJTYPE_POWERRES: {
|
|
|
|
dprintf(
|
|
"%02I64x <Power Resource> ",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_PowerResObj);
|
|
|
|
dprintf(
|
|
"SystemLevel=S%d Order=%x\n",
|
|
ReadField (bSystemLevel),
|
|
ReadField (bResOrder)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJTYPE_PROCESSOR: {
|
|
|
|
dprintf(
|
|
"%02I64x <Processor> ",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
if (InitTypeRead (pbDataBuffoffset, acpi!_ProcessorObj))
|
|
{
|
|
dprintf ("Error reading acpi!_ProcessorObj\n");
|
|
return;
|
|
}
|
|
|
|
dprintf(
|
|
"AcpiID=%016I64x PBlk=%016I64x PBlkLen=%016I64x\n",
|
|
ReadField (bApicID),
|
|
ReadField (dwPBlk),
|
|
ReadField (dwPBlkLen)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJTYPE_THERMALZONE:
|
|
|
|
dprintf(
|
|
"%02I64x <Thermal Zone>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFFIELD: {
|
|
|
|
dprintf(
|
|
"%02I64x <Buffer Field>",
|
|
ReadField (dwDataType)
|
|
);
|
|
|
|
InitTypeRead (pbDataBuffoffset, acpi!_BuffFieldObj);
|
|
|
|
dprintf(
|
|
"Ptr=%016I64x Len=%0164I64x Offset=%0164I64x Start=%016I64x NumBits=%x Flags=%x\n",
|
|
ReadField (pbDataBuff),
|
|
ReadField (dwBuffLen),
|
|
ReadField (FieldDesc.dwByteOffset),
|
|
ReadField (FieldDesc.dwStartBitPos),
|
|
ReadField (FieldDesc.dwNumBits),
|
|
ReadField (FieldDesc.dwFieldFlags)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OBJTYPE_DDBHANDLE:
|
|
dprintf(
|
|
"%02I64x <DDB Handle> Handle=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (pbDataBuff)
|
|
);
|
|
break;
|
|
case OBJTYPE_DEBUG:
|
|
dprintf(
|
|
"%02I64x <Internal Debug>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
case OBJTYPE_OBJALIAS:
|
|
|
|
dprintf(
|
|
"%02I64x <Internal Object Alias> NS Object=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (uipDataValue)
|
|
);
|
|
dumpNSObject( ReadField (uipDataValue), Verbose, IndentLevel + 2 );
|
|
break;
|
|
|
|
case OBJTYPE_DATAALIAS: {
|
|
|
|
dprintf(
|
|
"%02I64x <Internal Data Alias> Data Object=%016I64x\n",
|
|
ReadField (dwDataType),
|
|
ReadField (uipDataValue)
|
|
);
|
|
|
|
dumpObject(
|
|
ReadField (uipDataValue),
|
|
Verbose,
|
|
IndentLevel + 2
|
|
);
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_BANKFIELD:
|
|
|
|
dprintf(
|
|
"%02I64x <Internal Bank Field>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_FIELD:
|
|
|
|
dprintf(
|
|
"%02I64x <Internal Field>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_INDEXFIELD:
|
|
|
|
dprintf(
|
|
"%02I64x <Index Field>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_UNKNOWN:
|
|
default:
|
|
|
|
dprintf(
|
|
"%02I64x <Unknown>\n",
|
|
ReadField (dwDataType)
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
DECLARE_API( nsobj )
|
|
{
|
|
ULONG64 address = 0;
|
|
|
|
if (!strlen(args)) {
|
|
|
|
ReadPointer(GetExpression ("acpi!gpnsnamespaceroot"), &address);
|
|
|
|
} else {
|
|
|
|
address = UtilStringToUlong64 ((UCHAR *)args);
|
|
}
|
|
|
|
if (!address) {
|
|
|
|
dprintf ("nsobj: Error parsing arguments\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dprintf ("nsobj: dumping object at %I64x\n", address);
|
|
|
|
dumpNSObject( address, 0xFFFF, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
VOID
|
|
dumpNSObject(
|
|
IN ULONG64 Address,
|
|
IN ULONG Verbose,
|
|
IN ULONG IndentLevel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function dumps a Name space object
|
|
|
|
Arguments:
|
|
|
|
Address - Where to find the object
|
|
Verbose - Should the object be dumped as well?
|
|
IndentLevel - How much to indent
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG64 s;
|
|
UCHAR buffer[5];
|
|
UCHAR indent[80];
|
|
ULONG offset = 0;
|
|
|
|
//
|
|
// Init the buffers
|
|
//
|
|
IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel);
|
|
memset( indent, ' ', IndentLevel );
|
|
indent[IndentLevel] = '\0';
|
|
buffer[4] = '\0';
|
|
|
|
//
|
|
// First step is to read the root NS
|
|
//
|
|
|
|
s = InitTypeRead (Address, acpi!_NSObj);
|
|
|
|
if (s) {
|
|
|
|
dprintf("%sdumpNSObject: could not read %x(%I64x)\n", indent,Address,s);
|
|
return;
|
|
|
|
}
|
|
|
|
s = ReadField (dwNameSeg);
|
|
|
|
if (ReadField(dwNameSeg) != 0) {
|
|
|
|
memcpy( buffer, (UCHAR *) &s, 4 );
|
|
|
|
} else {
|
|
|
|
sprintf( buffer, " ");
|
|
|
|
}
|
|
|
|
dprintf(
|
|
"%sNameSpace Object %s (%016I64x) - Device %016I64x\n",
|
|
indent,
|
|
buffer,
|
|
Address,
|
|
ReadField (Context)
|
|
);
|
|
|
|
if (Verbose & VERBOSE_NSOBJ) {
|
|
|
|
dprintf(
|
|
"%s Flink %016I64x Blink %016I64x\n%s Parent %016I64x Child %016I64x\n",
|
|
indent,
|
|
ReadField (list.plistNext),
|
|
ReadField (list.plistPrev),
|
|
indent,
|
|
ReadField (pnsParent),
|
|
ReadField (pnsFirstChild)
|
|
);
|
|
|
|
}
|
|
|
|
dprintf(
|
|
"%s Value %016I64x Length %016I64x\n%s Buffer %016I64x Flags %016I64x\n",
|
|
indent,
|
|
ReadField (ObjData.uipDataValue),
|
|
ReadField (ObjData.dwDataLen),
|
|
indent,
|
|
ReadField (ObjData.pbDataBuff),
|
|
ReadField (ObjData.dwfData)
|
|
);
|
|
|
|
if (ReadField (ObjData.dwfData) & DATAF_BUFF_ALIAS) {
|
|
|
|
dprintf(" Alias" );
|
|
|
|
}
|
|
if (ReadField (ObjData.dwfData) & DATAF_GLOBAL_LOCK) {
|
|
|
|
dprintf(" Lock");
|
|
|
|
}
|
|
dprintf("\n");
|
|
|
|
GetFieldOffset ("acpi!_NSObj", "ObjData", (ULONG *) &offset);
|
|
|
|
dumpObject(Address + offset, Verbose, IndentLevel + 4);
|
|
}
|
|
|
|
|
|
VOID
|
|
dumpNSTree(
|
|
IN ULONG64 Address,
|
|
IN ULONG Level
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This thing dumps the NS tree
|
|
|
|
Arguments:
|
|
|
|
Address - Where to find the root node --- we start dumping at the children
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
BOOL end = FALSE;
|
|
ULONG64 s;
|
|
UCHAR buffer[5];
|
|
ULONG64 next;
|
|
ULONG back;
|
|
ULONG64 m1 = 0;
|
|
ULONG64 m2 = 0;
|
|
ULONG reason;
|
|
ULONG64 dataBuffSize;
|
|
UCHAR StrBuffer[2048];
|
|
ULONG64 r = 0;
|
|
|
|
buffer[4] = '\0';
|
|
memset( StrBuffer, '0', 2048 );
|
|
|
|
|
|
//
|
|
// Indent
|
|
//
|
|
for (m1 = 0; m1 < Level; m1 ++) {
|
|
|
|
dprintf("| ");
|
|
|
|
}
|
|
|
|
//
|
|
// First step is to read the root NS
|
|
//
|
|
|
|
InitTypeRead (Address, acpi!_NSObj);
|
|
|
|
if (ReadField (dwNameSeg) != 0) {
|
|
|
|
s = ReadField (dwNameSeg);
|
|
memcpy( buffer, (UCHAR*) &s, 4 );
|
|
dprintf("%4s ", buffer );
|
|
|
|
} else {
|
|
|
|
dprintf(" " );
|
|
|
|
}
|
|
dprintf(
|
|
"(%016I64x) - ", Address );
|
|
|
|
if (ReadField (Context) != 0) {
|
|
|
|
dprintf("Device %016I64x\n", ReadField (Context) );
|
|
|
|
} else {
|
|
|
|
//
|
|
// We need to read the pbDataBuff here
|
|
//
|
|
|
|
switch(ReadField (ObjData.dwDataType)) {
|
|
default:
|
|
case OBJTYPE_UNKNOWN: dprintf("Unknown\n"); break;
|
|
case OBJTYPE_INTDATA:
|
|
|
|
dprintf("Integer - %016I64x\n", ReadField (ObjData.uipDataValue));
|
|
break;
|
|
|
|
case OBJTYPE_STRDATA:
|
|
|
|
dataBuffSize = (ReadField (ObjData.dwDataLen) > 2047 ?
|
|
2047 : ReadField (ObjData.dwDataLen));
|
|
|
|
//dprintf ("blah:%016I64x, %lx\n", ReadField (ObjData.pbDataBuff), dataBuffSize);
|
|
|
|
ReadMemory(
|
|
ReadField (ObjData.pbDataBuff),
|
|
StrBuffer,
|
|
(ULONG) dataBuffSize,
|
|
NULL
|
|
);
|
|
|
|
if (!s) {
|
|
|
|
dprintf(
|
|
"dumpNSTree: could not read %x\n",
|
|
ReadField (ObjData.pbDataBuff)
|
|
);
|
|
return;
|
|
|
|
}
|
|
|
|
StrBuffer[dataBuffSize+1] = '\0';
|
|
|
|
dprintf(
|
|
"String - %s\n",
|
|
StrBuffer
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFDATA:
|
|
|
|
dprintf(
|
|
"Buffer - %08lx L=%04x\n",
|
|
ReadField (ObjData.pbDataBuff),
|
|
ReadField (ObjData.dwDataLen)
|
|
);
|
|
break;
|
|
|
|
case OBJTYPE_PKGDATA: {
|
|
|
|
InitTypeRead (ReadField (ObjData.pbDataBuff), acpi!_PackageObj);
|
|
|
|
dprintf("Package - NumElements %x\n", ReadField (dwcElements));
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_FIELDUNIT:{
|
|
|
|
InitTypeRead (ReadField (ObjData.pbDataBuff), acpi!_FieldUnitObj);
|
|
|
|
dprintf(
|
|
"FieldUnit - Parent %016I64x Offset %016I64x Start %016I64x "
|
|
"Num %016I64x Flags %016I64x\n",
|
|
ReadField (pnsFieldParent),
|
|
ReadField (FieldDesc.dwByteOffset),
|
|
ReadField (FieldDesc.dwStartBitPos),
|
|
ReadField (FieldDesc.dwNumBits),
|
|
ReadField (FieldDesc.dwFieldFlags)
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_DEVICE:
|
|
|
|
dprintf("Device\n");
|
|
break;
|
|
|
|
case OBJTYPE_EVENT:
|
|
|
|
dprintf("Event - PKEvent %016I64x\n", ReadField (ObjData.pbDataBuff));
|
|
break;
|
|
|
|
case OBJTYPE_METHOD: {
|
|
|
|
ULONG64 size, offset, pbdatabuff;
|
|
|
|
pbdatabuff = ReadField (ObjData.pbDataBuff);
|
|
size = ReadField (ObjData.dwDataLen);
|
|
GetFieldOffset ("acpi!_MethodObj", "abCodeBuff", (ULONG*) &offset);
|
|
|
|
InitTypeRead (pbdatabuff, acpi!_MethodObj);
|
|
|
|
dprintf(
|
|
"Method - Flags %016I64x Start %016I64x Len %016I64x\n",
|
|
ReadField (bMethodFlags),
|
|
offset + pbdatabuff,
|
|
size - GetTypeSize ("acpi!_MethodObj") + ANYSIZE_ARRAY
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_OPREGION: {
|
|
|
|
InitTypeRead (ReadField (ObjData.pbDataBuff), acpi!_OpRegionObj);
|
|
|
|
dprintf(
|
|
"Opregion - RegionsSpace=%02x OffSet=%016I64x Len=%016I64x\n",
|
|
ReadField (bRegionSpace),
|
|
ReadField (uipOffset),
|
|
ReadField (dwLen)
|
|
);
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_BUFFFIELD: {
|
|
|
|
InitTypeRead (ReadField (ObjData.pbDataBuff), acpi!_BuffFieldObj);
|
|
|
|
dprintf(
|
|
"Buffer Field Ptr=%x Len=%x Offset=%x Start=%x"
|
|
"NumBits=%x Flgas=%x\n",
|
|
ReadField (pbDataBuff),
|
|
ReadField (dwBuffLen),
|
|
ReadField (FieldDesc.dwByteOffset),
|
|
ReadField (FieldDesc.dwStartBitPos),
|
|
ReadField (FieldDesc.dwNumBits),
|
|
ReadField (FieldDesc.dwFieldFlags)
|
|
);
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_FIELD: {
|
|
|
|
dprintf("Field\n");
|
|
break;
|
|
|
|
}
|
|
case OBJTYPE_INDEXFIELD: dprintf("Index Field\n"); break;
|
|
|
|
case OBJTYPE_MUTEX: dprintf("Mutex\n"); break;
|
|
case OBJTYPE_POWERRES: dprintf("Power Resource\n"); break;
|
|
case OBJTYPE_PROCESSOR: dprintf("Processor\n"); break;
|
|
case OBJTYPE_THERMALZONE: dprintf("Thermal Zone\n"); break;
|
|
case OBJTYPE_DDBHANDLE: dprintf("DDB Handle\n"); break;
|
|
case OBJTYPE_DEBUG: dprintf("Debug\n"); break;
|
|
case OBJTYPE_OBJALIAS: dprintf("Object Alias\n"); break;
|
|
case OBJTYPE_DATAALIAS: dprintf("Data Alias\n"); break;
|
|
case OBJTYPE_BANKFIELD: dprintf("Bank Field\n"); break;
|
|
|
|
}
|
|
|
|
}
|
|
m1 = next = ReadField (pnsFirstChild);
|
|
|
|
while (next != 0 && end == FALSE) {
|
|
|
|
if (CheckControlC()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
dumpNSTree( next, Level + 1);
|
|
InitTypeRead (next, acpi!_NSObj);
|
|
|
|
//
|
|
// Do the end check tests
|
|
//
|
|
if ( m2 == 0) {
|
|
|
|
m2 = ReadField (list.plistPrev);
|
|
|
|
} else if (m1 == ReadField (list.plistNext)) {
|
|
|
|
end = TRUE;
|
|
reason = 1;
|
|
|
|
} else if (m2 == next) {
|
|
|
|
end = TRUE;
|
|
reason = 2;
|
|
}
|
|
|
|
next = ReadField (list.plistNext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DECLARE_API( nstree )
|
|
{
|
|
ULONG64 address = 0;
|
|
|
|
if (!strlen(args)) {
|
|
|
|
ReadPointer(GetExpression ("acpi!gpnsnamespaceroot"), &address);
|
|
|
|
} else {
|
|
|
|
address = UtilStringToUlong64 ((UCHAR *)args);
|
|
}
|
|
|
|
if (!address) {
|
|
|
|
dprintf ("nstree: Error parsing arguments\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dprintf ("nstree: dumping object at %I64x\n", address);
|
|
|
|
dumpNSTree( address, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Flags for interrupt vectors
|
|
//
|
|
|
|
#define VECTOR_MODE 1
|
|
#define VECTOR_LEVEL 1
|
|
#define VECTOR_EDGE 0
|
|
#define VECTOR_POLARITY 2
|
|
#define VECTOR_ACTIVE_LOW 2
|
|
#define VECTOR_ACTIVE_HIGH 0
|
|
|
|
//
|
|
// Vector Type:
|
|
//
|
|
// VECTOR_SIGNAL = standard edge-triggered or
|
|
// level-sensitive interrupt vector
|
|
//
|
|
// VECTOR_MESSAGE = an MSI (Message Signalled Interrupt) vector
|
|
//
|
|
|
|
#define VECTOR_TYPE 4
|
|
#define VECTOR_SIGNAL 0
|
|
#define VECTOR_MESSAGE 4
|
|
|
|
#define IS_LEVEL_TRIGGERED(vectorFlags) \
|
|
(vectorFlags & VECTOR_LEVEL)
|
|
|
|
#define IS_EDGE_TRIGGERED(vectorFlags) \
|
|
!(vectorFlags & VECTOR_LEVEL)
|
|
|
|
#define IS_ACTIVE_LOW(vectorFlags) \
|
|
(vectorFlags & VECTOR_ACTIVE_LOW)
|
|
|
|
#define IS_ACTIVE_HIGH(vectorFlags) \
|
|
!(vectorFlags & VECTOR_ACTIVE_LOW)
|
|
|
|
#define TOKEN_VALUE 0x57575757
|
|
#define EMPTY_BLOCK_VALUE 0x58585858
|
|
#define VECTOR_HASH_TABLE_LENGTH 0x1f
|
|
#define VECTOR_HASH_TABLE_WIDTH 2
|
|
|
|
VOID
|
|
dumpHashTableEntry(
|
|
IN ULONG64 VectorBlock
|
|
)
|
|
{
|
|
InitTypeRead (VectorBlock, acpi!_VECTOR_BLOCK);
|
|
|
|
dprintf("%04x Count/temp: %02d/%02d ",
|
|
ReadField (Entry.Vector),
|
|
ReadField (Entry.Count),
|
|
ReadField (Entry.TempCount));
|
|
|
|
dprintf("Flags: (%s %s) TempFlags(%s %s)\n",
|
|
(ReadField (Entry.Flags) & VECTOR_MODE) == VECTOR_LEVEL ?
|
|
"level" : "edge",
|
|
(ReadField (Entry.Flags) & VECTOR_POLARITY) == VECTOR_ACTIVE_LOW ?
|
|
"low" : "high",
|
|
(ReadField (Entry.TempFlags) & VECTOR_MODE) == VECTOR_LEVEL ?
|
|
"level" : "edge",
|
|
(ReadField (Entry.TempFlags) & VECTOR_POLARITY) == VECTOR_ACTIVE_LOW ?
|
|
"low" : "high");
|
|
|
|
}
|
|
|
|
VOID
|
|
dumpIrqArb(
|
|
IN ULONG64 IrqArb
|
|
)
|
|
{
|
|
ULONG64 Address;
|
|
ULONG64 Flink;
|
|
LIST_ENTRY64 ListEntry;
|
|
ULONG64 nextNode;
|
|
ULONG64 ListHead;
|
|
ULONG64 linkNode;
|
|
ULONG64 attachedDevs;
|
|
ULONG attachedDevOffset;
|
|
ULONG64 hashTable, hashTablePtr;
|
|
ULONG64 hashEntry;
|
|
ULONG hashEntrySize;
|
|
ULONG i,j;
|
|
ULONG64 retVal;
|
|
|
|
retVal = InitTypeRead (IrqArb, nt!_ARBITER_INSTANCE);
|
|
if (retVal) {
|
|
dprintf("Failed to get symbol nt!_ARBITER_INSTANCE\n");
|
|
return;
|
|
}
|
|
|
|
Address = ReadField(Extension);
|
|
dprintf("ACPI IRQ Arbiter: %016I64x Extension: %016I64x\n",
|
|
IrqArb, Address);
|
|
|
|
retVal = InitTypeRead (Address, acpi!ARBITER_EXTENSION);
|
|
if (retVal) {
|
|
dprintf("Failed to get symbol acpi!ARBITER_EXTENSION\n");
|
|
return;
|
|
}
|
|
|
|
ListHead = ReadField(LinkNodeHead);
|
|
dprintf("\nLink nodes in use: (list head at %016I64x )\n", ListHead);
|
|
|
|
ListEntry.Flink = ReadField(LinkNodeHead.Flink);
|
|
ListEntry.Blink = Address;
|
|
|
|
//dprintf("%016I64x, %016I64x\n", ListEntry.Flink, ListEntry.Blink);
|
|
|
|
if (ListHead == ListEntry.Flink) {
|
|
dprintf("\tNone.\n");
|
|
}
|
|
|
|
if (GetFieldOffset("acpi!LINK_NODE", "AttachedDevices", &attachedDevOffset)) {
|
|
dprintf("symbol lookup acpi!LINK_NODE failed\n");
|
|
return;
|
|
}
|
|
|
|
nextNode = ListEntry.Flink;
|
|
|
|
while (nextNode != ListEntry.Blink) {
|
|
|
|
//dprintf("nextNode: %016I64x\n", nextNode);
|
|
retVal = InitTypeRead (nextNode, acpi!LINK_NODE);
|
|
if (retVal) {
|
|
dprintf("Failed to get type acpi!LINK_NODE\n");
|
|
break;
|
|
}
|
|
|
|
dprintf("\n");
|
|
dumpNSObject( ReadField(NameSpaceObject), 0xFFFF, 3 );
|
|
InitTypeRead (nextNode, acpi!LINK_NODE);
|
|
dprintf("\n\tVector/temp: (%x/%x) RefCount/temp: (%d/%d) Flags: %x\n",
|
|
(ULONG)(ReadField(CurrentIrq) & 0xffffffff),
|
|
(ULONG)(ReadField(TempIrq) & 0xffffffff),
|
|
ReadField(ReferenceCount),
|
|
ReadField(TempRefCount),
|
|
ReadField(Flags));
|
|
|
|
attachedDevs = ReadField(AttachedDevices.Next);
|
|
//dprintf("attachedDevs: %p nextNode: %p attachedDevOffset: %x\n",
|
|
// attachedDevs, nextNode, attachedDevOffset);
|
|
|
|
while (attachedDevs != (nextNode + attachedDevOffset)) {
|
|
|
|
InitTypeRead(attachedDevs, acpi!LINK_NODE_ATTACHED_DEVICES);
|
|
|
|
//dprintf("\t\tAttached PDO: %016I64x\n", ReadField(Pdo));
|
|
|
|
attachedDevs = ReadField(List.Next);
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
InitTypeRead (nextNode, acpi!LINK_NODE);
|
|
nextNode = ReadField(List.Flink);
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
hashTablePtr = GetExpression( "acpi!irqhashtable" );
|
|
if (!hashTablePtr) {
|
|
dprintf("couldn't read symbol acpi!irqhashtable\n");
|
|
return;
|
|
}
|
|
|
|
retVal = ReadPointer(hashTablePtr, &hashTable);
|
|
if (!retVal) {
|
|
return;
|
|
}
|
|
|
|
hashEntrySize = GetTypeSize("acpi!_VECTOR_BLOCK");
|
|
|
|
dprintf("\n\nIRQ Hash Table (at %016I64x ):\n",
|
|
hashTable);
|
|
|
|
for (i = 0; i < VECTOR_HASH_TABLE_LENGTH; i++) {
|
|
|
|
hashEntry = hashTable + (i * VECTOR_HASH_TABLE_WIDTH * hashEntrySize);
|
|
|
|
DumpVectorTableStartRow:
|
|
for (j = 0; j < VECTOR_HASH_TABLE_WIDTH; j++) {
|
|
|
|
InitTypeRead(hashEntry, acpi!_VECTOR_BLOCK);
|
|
|
|
if (ReadField(Chain.Token) == TOKEN_VALUE) {
|
|
|
|
hashEntry = ReadField(Chain.Next);
|
|
|
|
dumpHashTableEntry(hashEntry);
|
|
|
|
goto DumpVectorTableStartRow;
|
|
}
|
|
|
|
if (ReadField(Entry.Vector) != EMPTY_BLOCK_VALUE) {
|
|
|
|
dumpHashTableEntry(hashEntry);
|
|
}
|
|
|
|
hashEntry += hashEntrySize;
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DECLARE_API( acpiirqarb )
|
|
{
|
|
ULONG64 irqArbiter;
|
|
|
|
irqArbiter = GetExpression( "acpi!acpiarbiter" );
|
|
|
|
if (!irqArbiter) {
|
|
dprintf("failed to find address of arbiter\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
dumpIrqArb(irqArbiter);
|
|
|
|
return S_OK;
|
|
}
|