2003-08-11 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / kd / kdebug.c
index 48fcaf6..03b72a0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: kdebug.c,v 1.13 2000/08/12 19:33:21 dwelch Exp $
+/* $Id: kdebug.c,v 1.46 2003/08/11 18:50:12 chorns Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
 #include <ddk/ntddk.h>
 #include <internal/ntoskrnl.h>
 #include <internal/kd.h>
-#include <stdlib.h>
-#include <ctype.h>
-
+#include <internal/mm.h>
+#include <roscfg.h>
+#include "../dbg/kdb.h"
 
 /* serial debug connection */
 #define DEFAULT_DEBUG_PORT      2      /* COM2 */
-#define DEFAULT_DEBUG_BAUD_RATE 19200  /* 19200 Baud */
+#define DEFAULT_DEBUG_COM1_IRQ  4      /* COM1 IRQ */
+#define DEFAULT_DEBUG_COM2_IRQ  3      /* COM2 IRQ */
+#define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
 
 /* bochs debug output */
 #define BOCHS_LOGGER_PORT (0xe9)
 
-
-/* TYPEDEFS ****************************************************************/
-
-#define ScreenDebug  (0x1)
-#define SerialDebug  (0x2)
-#define BochsDebug   (0x4)
-
 /* VARIABLES ***************************************************************/
 
 BOOLEAN
@@ -42,286 +37,438 @@ KdDebuggerNotPresent = TRUE;              /* EXPORTED */
 
 
 static BOOLEAN KdpBreakPending = FALSE;
-static BOOLEAN KdpBreakRecieved = FALSE;
-static ULONG KdpDebugType = BochsDebug;
+ULONG KdDebugState = KD_DEBUG_DISABLED;
+ULONG KdpPortIrq = 0;
 
+KD_PORT_INFORMATION GdbPortInfo;
+KD_PORT_INFORMATION LogPortInfo;
 
 /* PRIVATE FUNCTIONS ********************************************************/
 
-static void
-PrintString (char* fmt,...)
+static VOID
+PrintString(char* fmt,...)
 {
-       char buffer[512];
-       va_list ap;
+  char buffer[512];
+  va_list ap;
 
-       va_start(ap, fmt);
-       vsprintf(buffer, fmt, ap);
-       va_end(ap);
+  va_start(ap, fmt);
+  vsprintf(buffer, fmt, ap);
+  va_end(ap);
 
-       HalDisplayString (buffer);
+  HalDisplayString(buffer);
 }
 
 
 VOID
-KdInitSystem (
-       ULONG                   Reserved,
-       PLOADER_PARAMETER_BLOCK LoaderBlock
-       )
+KdInitSystem(ULONG Reserved,
+            PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-       KD_PORT_INFORMATION PortInfo;
-       ULONG Value;
-       PCHAR p1, p2;
+  KD_PORT_INFORMATION PortInfo;
+  ULONG Value;
+  PCHAR p1, p2;
+
+#ifdef KDBG
+  /* Initialize runtime debugging if available */
+  DbgRDebugInit();
+#endif
 
-       /* set debug port default values */
-       PortInfo.ComPort  = DEFAULT_DEBUG_PORT;
-       PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
+#ifdef KDBG
+  /* Initialize the local kernel debugger. */
+  KdDebuggerEnabled = TRUE;
+  KdDebugState |= KD_DEBUG_KDB;
+#endif
+
+  /* Set debug port default values */
+  PortInfo.ComPort = DEFAULT_DEBUG_PORT;
+  PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
+  KdpPortIrq = DEFAULT_DEBUG_COM2_IRQ;
+
+  /* Set serial log port default values */
+  LogPortInfo.ComPort = DEFAULT_DEBUG_PORT;
+  LogPortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
 
-       /*
-        * parse kernel command line
-        */
+  /* Parse kernel command line */
 
-       /* check for 'DEBUGPORT' */
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
+  /* Check for 'DEBUGPORT' */
+  p1 = (PCHAR)LoaderBlock->CommandLine;
+  while (p1 && (p2 = strchr(p1, '/')))
+    {
+      p2++;
+      if (!_strnicmp(p2, "DEBUGPORT", 9))
        {
-               p2++;
-               if (!_strnicmp (p2, "DEBUGPORT", 9))
+         p2 += 9;
+         if (*p2 == '=')
+           {
+             p2++;
+             if (!_strnicmp(p2, "SCREEN", 6))
                {
-                       p2 += 9;
-                       if (*p2 != '=')
-                               break;
-                       p2++;
-                       if (!_strnicmp (p2, "SCREEN", 6))
-                       {
-                               p2 += 6;
-                               KdDebuggerEnabled = TRUE;
-                               KdpDebugType |= ScreenDebug;
-                       }
-                       else if (!_strnicmp (p2, "BOCHS", 5))
-                       {
-                               p2 += 5;
-                               KdDebuggerEnabled = TRUE;
-                               KdpDebugType |= BochsDebug;
-                       }
-                       else if (!_strnicmp (p2, "COM", 3))
-                       {
-                               p2 += 3;
-                               Value = (ULONG)atol (p2);
-                               if (Value > 0 && Value < 5)
-                               {
-                                       KdDebuggerEnabled = TRUE;
-                                       KdpDebugType |= SerialDebug;
-                                       PortInfo.ComPort = Value;
-                               }
-                       }
-                       break;
+                 p2 += 6;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_SCREEN;
                }
-               p1 = p2;
-       }
-
-       /* check for 'BAUDRATE' */
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
-       {
-               p2++;
-               if (!_strnicmp (p2, "BAUDRATE", 8))
+             else if (!_strnicmp(p2, "BOCHS", 5))
                {
-                       p2 += 8;
-                       if (*p2 != '=')
-                               break;
-                       p2++;
-                       Value = (ULONG)atol (p2);
-                       if (Value > 0)
-                       {
-                               KdDebuggerEnabled = TRUE;
-                               KdpDebugType = KdpDebugType | SerialDebug;
-                               PortInfo.BaudRate = Value;
-                       }
-                       break;
+                 p2 += 5;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_BOCHS;
                }
-               p1 = p2;
-       }
-
-       /* Check for 'DEBUG'. Dont' accept 'DEBUGPORT'!*/
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
-       {
-               p2++;
-               if (!_strnicmp (p2, "DEBUG", 5) &&
-                   _strnicmp (p2, "DEBUGPORT", 9))
+             else if (!_strnicmp(p2, "GDB", 3))
                {
-                       p2 += 5;
-                       KdDebuggerEnabled = TRUE;
-                       KdpDebugType = KdpDebugType | SerialDebug;
-                       break;
+                 p2 += 3;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_GDB;
+
+                 /* Reset port information to defaults */
+                 RtlMoveMemory(&GdbPortInfo, &PortInfo, sizeof(KD_PORT_INFORMATION));
+                 PortInfo.ComPort = DEFAULT_DEBUG_PORT;
+                 PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
                }
-               p1 = p2;
-       }
-
-       /* Check for 'NODEBUG' */
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
-       {
-               p2++;
-               if (!_strnicmp (p2, "NODEBUG", 7))
+             else if (!_strnicmp(p2, "PICE", 4))
                {
-                       p2 += 7;
-                       KdDebuggerEnabled = FALSE;
-                       break;
+                 p2 += 4;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_PICE;
                }
-               p1 = p2;
-       }
-
-       /* Check for 'CRASHDEBUG' */
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
-       {
-               p2++;
-               if (!_strnicmp (p2, "CRASHDEBUG", 10))
+             else if (!_strnicmp(p2, "COM", 3))
                {
-                       p2 += 10;
-                       KdDebuggerEnabled = FALSE;
-                       break;
+                 p2 += 3;
+                 Value = (ULONG)atol(p2);
+                 if (Value > 0 && Value < 5)
+                   {
+                     KdDebuggerEnabled = TRUE;
+                         KdDebugState |= KD_DEBUG_SERIAL;
+                     LogPortInfo.ComPort = Value;
+                   }
                }
-               p1 = p2;
-       }
-
-       /* Check for 'BREAK' */
-       p1 = LoaderBlock->kernel_parameters;
-       while (p1 && (p2 = strchr (p1, '/')))
-       {
-               p2++;
-               if (!_strnicmp (p2, "BREAK", 5))
+             else if (!_strnicmp(p2, "FILE", 4))
                {
-                       p2 += 7;
-                       KdpBreakPending = TRUE;
-                       break;
+                 p2 += 4;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_FILELOG;
                }
-               p1 = p2;
+             else if (!_strnicmp(p2, "MDA", 3))
+               {
+                 p2 += 3;
+                 KdDebuggerEnabled = TRUE;
+                 KdDebugState |= KD_DEBUG_MDA;
+               }
+           }
        }
-
-
-       /* print some information */
-       if (KdDebuggerEnabled == TRUE)
+      else if (!_strnicmp(p2, "DEBUG", 5))
+       {
+         p2 += 5;
+         KdDebuggerEnabled = TRUE;
+         KdDebugState |= KD_DEBUG_SERIAL;
+       }
+      else if (!_strnicmp(p2, "NODEBUG", 7))
+       {
+         p2 += 7;
+         KdDebuggerEnabled = FALSE;
+         KdDebugState = KD_DEBUG_DISABLED;
+       }
+      else if (!_strnicmp(p2, "CRASHDEBUG", 10))
+       {
+         p2 += 10;
+         KdDebuggerEnabled = FALSE;
+         KdDebugState = KD_DEBUG_DISABLED;
+       }
+      else if (!_strnicmp(p2, "BREAK", 5))
+       {
+         p2 += 5;
+         KdpBreakPending = TRUE;
+       }
+      else if (!_strnicmp(p2, "COM", 3))
        {
-               if (KdpDebugType & ScreenDebug)
+         p2 += 3;
+         if ('=' == *p2)
+           {
+             p2++;
+             Value = (ULONG)atol(p2);
+             if (0 < Value && Value < 5)
                {
-                       PrintString ("\n   Screen debugging enabled\n\n");
+                 PortInfo.ComPort = Value;
                }
-               if (KdpDebugType & BochsDebug)
+           }
+       }
+      else if (!_strnicmp(p2, "BAUDRATE", 8))
+       {
+         p2 += 8;
+         if ('=' == *p2)
+           {
+             p2++;
+             Value = (ULONG)atol(p2);
+             if (0 < Value)
                {
-                       PrintString ("\n   Bochs debugging enabled\n\n");
+                 PortInfo.BaudRate = Value;
                }
-               if (KdpDebugType & SerialDebug)
+           }
+       }
+      else if (!_strnicmp(p2, "IRQ", 3))
+       {
+         p2 += 3;
+         if ('=' == *p2)
+           {
+             p2++;
+             Value = (ULONG)atol(p2);
+             if (0 < Value)
                {
-                       PrintString ("\n   Serial debugging enabled: COM%ld %ld Baud\n\n",
-                                    PortInfo.ComPort, PortInfo.BaudRate);
+                 KdpPortIrq = Value;
                }
+           }
        }
-       else
-               PrintString ("\n   Debugging disabled\n\n");
+#ifdef KDBG
+    else if (!_strnicmp(p2, "PROFILE", 7))
+      {
+        KdbInitProfiling();
+      }
+#endif /* KDBG */
+      p1 = p2;
+    }
+
+  /* Perform any initialization nescessary */
+  if (KdDebuggerEnabled == TRUE)
+    {
+      if (KdDebugState & KD_DEBUG_GDB)
+           KdPortInitializeEx(&GdbPortInfo, 0, 0);
+
+      if (KdDebugState & KD_DEBUG_SERIAL)
+           KdPortInitializeEx(&LogPortInfo, 0, 0);
+
+      if (KdDebugState & KD_DEBUG_FILELOG)
+           DebugLogInit();
+
+      if (KdDebugState & KD_DEBUG_MDA)
+           KdInitializeMda();
+    }
+}
 
 
-       /* initialize debug port */
-       if (KdDebuggerEnabled && KdpDebugType == SerialDebug)
-       {
-               KdPortInitialize (&PortInfo,
-                                 0,
-                                 0);
-       }
+VOID
+KdInit1(VOID)
+{
+  /* Initialize kernel debugger (phase 0) */
+  if ((KdDebuggerEnabled == TRUE) &&
+      (KdDebugState & KD_DEBUG_GDB))
+    {
+      KdGdbStubInit(0);
+    }
 }
 
 
-ULONG KdpPrintString (PANSI_STRING String)
+VOID KdInit2(VOID)
 {
-   PCH pch = String->Buffer;
-   
-   if (KdpDebugType & ScreenDebug)
-     {
-       HalDisplayString (String->Buffer);
-     }
-   if (KdpDebugType & SerialDebug)
-     {
-       while (*pch != 0)
-         {
-            if (*pch == '\n')
-              {
-                 KdPortPutByte ('\r');
-              }
-            KdPortPutByte (*pch);
-            pch++;
-         }
-       }
-   if (KdpDebugType & BochsDebug)
-     {
-       while (*pch != 0)
+  /* Initialize kernel debugger (phase 1) */
+  if ((KdDebuggerEnabled == TRUE) &&
+      (KdDebugState & KD_DEBUG_GDB))
+    {
+      KdGdbStubInit(1);
+    }
+}
+
+
+VOID
+KdInit3(VOID)
+{
+  /* Print some information */
+  if (KdDebuggerEnabled == TRUE)
+    {
+      if (KdDebugState & KD_DEBUG_GDB)
+           PrintString("\n   GDB debugging enabled. COM%ld %ld Baud\n\n",
+                       GdbPortInfo.ComPort, GdbPortInfo.BaudRate);
+         
+      if (KdDebugState & KD_DEBUG_PICE)
+           PrintString("\n   Private ICE debugger enabled\n\n");
+
+      if (KdDebugState & KD_DEBUG_SCREEN)
+           PrintString("\n   Screen debugging enabled\n\n");
+
+      if (KdDebugState & KD_DEBUG_BOCHS)
+           PrintString("\n   Bochs debugging enabled\n\n");
+
+      if (KdDebugState & KD_DEBUG_SERIAL)
+           PrintString("\n   Serial debugging enabled. COM%ld %ld Baud\n\n",
+                       LogPortInfo.ComPort, LogPortInfo.BaudRate);
+
+      if (KdDebugState & KD_DEBUG_FILELOG)
+           PrintString("\n   File log debugging enabled\n\n");
+      if (KdDebugState & KD_DEBUG_MDA)
+           PrintString("\n   MDA debugging enabled\n\n");
+    }
+}
+
+
+VOID
+KdSerialDebugPrint (LPSTR Message)
+{
+  PCHAR pch = (PCHAR) Message;
+
+  while (*pch != 0)
+    {
+      if (*pch == '\n')
+        {
+          KdPortPutByteEx (&LogPortInfo, '\r');
+        }
+        KdPortPutByteEx (&LogPortInfo, *pch);
+        pch++;
+    }
+}
+
+
+VOID
+KdBochsDebugPrint(IN LPSTR  Message)
+{
+       while (*Message != 0)
          {
-            if (*pch == '\n')
-              {
-                 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
-              }
-            WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *pch);
-            pch++;
+           if (*Message == '\n')
+             {
+               WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
+             }
+           WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *Message);
+           Message++;
          }
-     }
-   
-   return (ULONG)String->Length;
+}
+
+
+ULONG
+KdpPrintString(PANSI_STRING String)
+{
+       PCH pch = String->Buffer;
+
+       if (KdDebugState & KD_DEBUG_GDB)
+               KdGdbDebugPrint(pch);
+
+       if (KdDebugState & KD_DEBUG_SCREEN)
+               HalDisplayString(pch);
+
+       if (KdDebugState & KD_DEBUG_SERIAL)
+               KdSerialDebugPrint(pch);
+
+       if (KdDebugState & KD_DEBUG_BOCHS)
+               KdBochsDebugPrint(pch);
+
+       if (KdDebugState & KD_DEBUG_FILELOG)
+               DebugLogWrite(pch);
+
+       if (KdDebugState & KD_DEBUG_MDA)
+               KdPrintMda(pch);
+
+       return((ULONG)String->Length);
 }
 
 /* PUBLIC FUNCTIONS *********************************************************/
 
 /* NTOSKRNL.KdPollBreakIn */
 
-BOOLEAN
-STDCALL
-KdPollBreakIn (
-       VOID
-       )
+/*
+ * @implemented
+ */
+BOOLEAN STDCALL
+KdPollBreakIn(VOID)
 {
-       BOOLEAN Result = FALSE;
-       UCHAR ByteRead;
+  if ((!KdDebuggerEnabled) || (!(KdDebugState & KD_DEBUG_SERIAL)))
+    return FALSE;
+  return KdpBreakPending;
+}
 
-       if (KdDebuggerEnabled == FALSE || KdpDebugType != SerialDebug)
-               return Result;
+/*
+ * @implemented
+ */
+VOID STDCALL
+KeEnterKernelDebugger(VOID)
+{
+  HalDisplayString("\n\n *** Entered kernel debugger ***\n");
 
-//     Flags = KiDisableInterrupts();
+  for (;;)
+    __asm__("hlt\n\t");
+}
 
-       HalDisplayString ("Waiting for kernel debugger connection...\n");
+VOID STDCALL
+KdSystemDebugControl(ULONG Code)
+{
+  extern VOID PsDumpThreads(BOOLEAN IncludeSystem);
+
+  /* A - Dump the entire contents of the non-paged pool. */
+  if (Code == 0)
+    {
+      MiDebugDumpNonPagedPool(FALSE);
+    }
+  /* B - Bug check the system. */
+  else if (Code == 1)
+    {
+      KEBUGCHECK(0);
+    }
+  /* 
+   * C -  Dump statistics about the distribution of tagged blocks in 
+   *      the non-paged pool.
+   */
+  else if (Code == 2)
+    {
+      MiDebugDumpNonPagedPoolStats(FALSE);
+    }
+  /* 
+   * D - Dump the blocks created in the non-paged pool since the last
+   * SysRq + D and SysRq + E command.
+   */
+  else if (Code == 3)
+    {
+      MiDebugDumpNonPagedPool(TRUE);
+    }
+  /* E - Dump statistics about the tags of newly created blocks. */
+  else if (Code == 4)
+    {
+      MiDebugDumpNonPagedPoolStats(TRUE);
+    }
+  /* F */
+  else if (Code == 5)
+    {
+      PsDumpThreads(TRUE);
+    }
+  /* G */
+  else if (Code == 6)
+    {
+      PsDumpThreads(FALSE);
+    }
+  /* H */
+  else if (Code == 7)
+    {
+    }
+  /* I */
+  else if (Code == 8)
+    {
+    }
+  /* J */
+  else if (Code == 9)
+    {
+    }
+  /* K - Enter the system debugger. */
+  else if (Code == 10)
+    {
+#ifdef KDBG
+      KdbEnter();
+#else /* KDBG */
+      DbgPrint("No local kernel debugger\n");
+#endif /* not KDBG */
+    }
+}
 
-       if (KdPortPollByte (&ByteRead))
-       {
-               if (ByteRead == 0x62)
-               {
-                       if (KdpBreakPending == TRUE)
-                       {
-                               KdpBreakPending = FALSE;
-                               KdpBreakRecieved = TRUE;
-                               Result = TRUE;
-                       }
-                       HalDisplayString ("   Kernel debugger connected\n");
-               }
-               else
-               {
-                       HalDisplayString ("   Kernel debugger connection failed\n");
-               }
-       }
 
-//     KiRestoreInterrupts (Flags);
+/* Support routines for the GDB stubs */
 
-       return Result;
+VOID
+KdPutChar(UCHAR Value)
+{
+  KdPortPutByteEx (&GdbPortInfo, Value);
 }
 
-VOID STDCALL
-KeEnterKernelDebugger (VOID)
+
+UCHAR
+KdGetChar(VOID)
 {
-       HalDisplayString ("\n\n *** Entered kernel debugger ***\n");
+  UCHAR Value;
 
-#if 1
-       for (;;)
-               __asm__("hlt\n\t");
-#else
-   for(;;);
-#endif
+  while (!KdPortGetByteEx (&GdbPortInfo, &Value));
+
+  return Value;
 }
 
 /* EOF */