windows-nt/Source/XPSP1/NT/base/tools/kdexts2/acpi.c
2020-09-26 16:20:57 +08:00

3662 lines
95 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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