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