-/* $Id: kdebug.c,v 1.19 2001/02/14 02:53:53 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 <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)
-#define FileLogDebug (0x8)
-
/* VARIABLES ***************************************************************/
BOOLEAN
static BOOLEAN KdpBreakPending = FALSE;
-static BOOLEAN KdpBreakRecieved = FALSE;
-static ULONG KdpDebugType = ScreenDebug | 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;
- /* set debug port default values */
- PortInfo.ComPort = DEFAULT_DEBUG_PORT;
- PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
+#ifdef KDBG
+ /* Initialize runtime debugging if available */
+ DbgRDebugInit();
+#endif
- /*
- * parse kernel command line
- */
+#ifdef KDBG
+ /* Initialize the local kernel debugger. */
+ KdDebuggerEnabled = TRUE;
+ KdDebugState |= KD_DEBUG_KDB;
+#endif
- /* check for 'DEBUGPORT' */
- p1 = (PCHAR)LoaderBlock->CommandLine;
- while (p1 && (p2 = strchr (p1, '/')))
+ /* 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 */
+
+ /* 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 = (PCHAR)LoaderBlock->CommandLine;
- 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 = (PCHAR)LoaderBlock->CommandLine;
- 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 = (PCHAR)LoaderBlock->CommandLine;
- 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 = (PCHAR)LoaderBlock->CommandLine;
- 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 = (PCHAR)LoaderBlock->CommandLine;
- 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;
+ }
+ }
}
-
-#ifdef DBGPRINT_FILE_LOG
- KdpDebugType |= FileLogDebug;
- DebugLogInit();
-#endif /* DBGPRINT_FILE_LOG */
-
- /* 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;
}
- if (KdpDebugType & FileLogDebug)
- {
- PrintString("\n File log debugging enabled\n\n");
- }
+ }
}
- 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++;
}
- }
-#ifdef DBGPRINT_FILE_LOG
- if (KdpDebugType & FileLogDebug)
- {
- DebugLogWrite(String->Buffer);
- }
-#endif /* DBGPRINT_FILE_LOG */
- 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 */