PsInitProcessManagment(): Hack-fake process name "System"
[reactos.git] / ntoskrnl / kd / kdebug.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/kd/kdebug.c
6  * PURPOSE:         Kernel debugger
7  * PROGRAMMER:      Eric Kohl (ekohl@abo.rhein-zeitung.de)
8  * UPDATE HISTORY:
9  *                  21/10/99: Created
10  */
11
12 #include <ddk/ntddk.h>
13 #include <internal/ntoskrnl.h>
14 #include <internal/kd.h>
15 #include <internal/mm.h>
16 #include <roscfg.h>
17 #include "../dbg/kdb.h"
18
19 /* serial debug connection */
20 #define DEFAULT_DEBUG_PORT      2       /* COM2 */
21 #define DEFAULT_DEBUG_COM1_IRQ  4       /* COM1 IRQ */
22 #define DEFAULT_DEBUG_COM2_IRQ  3       /* COM2 IRQ */
23 #define DEFAULT_DEBUG_BAUD_RATE 115200  /* 115200 Baud */
24
25 /* bochs debug output */
26 #define BOCHS_LOGGER_PORT (0xe9)
27
28 /* VARIABLES ***************************************************************/
29
30 BOOLEAN
31 __declspec(dllexport)
32 KdDebuggerEnabled = FALSE;              /* EXPORTED */
33
34 BOOLEAN
35 __declspec(dllexport)
36 KdDebuggerNotPresent = TRUE;            /* EXPORTED */
37
38
39 static BOOLEAN KdpBreakPending = FALSE;
40 ULONG KdDebugState = KD_DEBUG_DISABLED;
41 ULONG KdpPortIrq = 0;
42
43 KD_PORT_INFORMATION GdbPortInfo;
44 KD_PORT_INFORMATION LogPortInfo;
45
46 /* PRIVATE FUNCTIONS ********************************************************/
47
48 static VOID
49 PrintString(char* fmt,...)
50 {
51   char buffer[512];
52   va_list ap;
53
54   va_start(ap, fmt);
55   vsprintf(buffer, fmt, ap);
56   va_end(ap);
57
58   HalDisplayString(buffer);
59 }
60
61
62 VOID
63 KdInitSystem(ULONG Reserved,
64              PLOADER_PARAMETER_BLOCK LoaderBlock)
65 {
66   KD_PORT_INFORMATION PortInfo;
67   ULONG Value;
68   PCHAR p1, p2;
69
70 #ifdef KDBG
71   /* Initialize runtime debugging if available */
72   DbgRDebugInit();
73 #endif
74
75 #ifdef KDBG
76   /* Initialize the local kernel debugger. */
77   KdDebuggerEnabled = TRUE;
78   KdDebugState |= KD_DEBUG_KDB;
79 #endif
80
81   /* Set debug port default values */
82   PortInfo.ComPort = DEFAULT_DEBUG_PORT;
83   PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
84   KdpPortIrq = DEFAULT_DEBUG_COM2_IRQ;
85
86   /* Set serial log port default values */
87   LogPortInfo.ComPort = DEFAULT_DEBUG_PORT;
88   LogPortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
89
90   /* Parse kernel command line */
91
92   /* Check for 'DEBUGPORT' */
93   p1 = (PCHAR)LoaderBlock->CommandLine;
94   while (p1 && (p2 = strchr(p1, '/')))
95     {
96       p2++;
97       if (!_strnicmp(p2, "DEBUGPORT", 9))
98         {
99           p2 += 9;
100           if (*p2 == '=')
101             {
102               p2++;
103               if (!_strnicmp(p2, "SCREEN", 6))
104                 {
105                   p2 += 6;
106                   KdDebuggerEnabled = TRUE;
107                   KdDebugState |= KD_DEBUG_SCREEN;
108                 }
109               else if (!_strnicmp(p2, "BOCHS", 5))
110                 {
111                   p2 += 5;
112                   KdDebuggerEnabled = TRUE;
113                   KdDebugState |= KD_DEBUG_BOCHS;
114                 }
115               else if (!_strnicmp(p2, "GDB", 3))
116                 {
117                   p2 += 3;
118                   KdDebuggerEnabled = TRUE;
119                   KdDebugState |= KD_DEBUG_GDB;
120
121                   /* Reset port information to defaults */
122                   RtlMoveMemory(&GdbPortInfo, &PortInfo, sizeof(KD_PORT_INFORMATION));
123                   PortInfo.ComPort = DEFAULT_DEBUG_PORT;
124                   PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
125                 }
126               else if (!_strnicmp(p2, "PICE", 4))
127                 {
128                   p2 += 4;
129                   KdDebuggerEnabled = TRUE;
130                   KdDebugState |= KD_DEBUG_PICE;
131                 }
132               else if (!_strnicmp(p2, "COM", 3))
133                 {
134                   p2 += 3;
135                   Value = (ULONG)atol(p2);
136                   if (Value > 0 && Value < 5)
137                     {
138                       KdDebuggerEnabled = TRUE;
139                           KdDebugState |= KD_DEBUG_SERIAL;
140                       LogPortInfo.ComPort = Value;
141                     }
142                 }
143               else if (!_strnicmp(p2, "FILE", 4))
144                 {
145                   p2 += 4;
146                   KdDebuggerEnabled = TRUE;
147                   KdDebugState |= KD_DEBUG_FILELOG;
148                 }
149               else if (!_strnicmp(p2, "MDA", 3))
150                 {
151                   p2 += 3;
152                   KdDebuggerEnabled = TRUE;
153                   KdDebugState |= KD_DEBUG_MDA;
154                 }
155             }
156         }
157       else if (!_strnicmp(p2, "DEBUG", 5))
158         {
159           p2 += 5;
160           KdDebuggerEnabled = TRUE;
161           KdDebugState |= KD_DEBUG_SERIAL;
162         }
163       else if (!_strnicmp(p2, "NODEBUG", 7))
164         {
165           p2 += 7;
166           KdDebuggerEnabled = FALSE;
167           KdDebugState = KD_DEBUG_DISABLED;
168         }
169       else if (!_strnicmp(p2, "CRASHDEBUG", 10))
170         {
171           p2 += 10;
172           KdDebuggerEnabled = FALSE;
173           KdDebugState = KD_DEBUG_DISABLED;
174         }
175       else if (!_strnicmp(p2, "BREAK", 5))
176         {
177           p2 += 5;
178           KdpBreakPending = TRUE;
179         }
180           else if (!_strnicmp(p2, "COM", 3))
181             {
182               p2 += 3;
183               if (*p2 != '=')
184                 {
185                   p2++;
186                   Value = (ULONG)atol(p2);
187                   if (Value > 0 && Value < 5)
188                     {
189                       PortInfo.ComPort = Value;
190                     }
191                 }
192         }
193       else if (!_strnicmp(p2, "BAUDRATE", 8))
194         {
195           p2 += 8;
196           if (*p2 != '=')
197             {
198               p2++;
199               Value = (ULONG)atol(p2);
200               if (Value > 0)
201                         {
202                           PortInfo.BaudRate = Value;
203                         }
204             }
205           else if (!_strnicmp(p2, "IRQ", 3))
206             {
207               p2 += 3;
208               if (*p2 != '=')
209                 {
210                   p2++;
211                   Value = (ULONG)atol(p2);
212                   if (Value > 0)
213                     {
214                       KdpPortIrq = Value;
215                     }
216                 }
217             }
218         }
219       p1 = p2;
220     }
221
222   /* Print some information */
223   if (KdDebuggerEnabled == TRUE)
224     {
225       if (KdDebugState & KD_DEBUG_GDB)
226             PrintString("\n   GDB debugging enabled. COM%ld %ld Baud\n\n",
227                         GdbPortInfo.ComPort, GdbPortInfo.BaudRate);
228           
229       if (KdDebugState & KD_DEBUG_PICE)
230             PrintString("\n   Private ICE debugger enabled\n\n");
231
232       if (KdDebugState & KD_DEBUG_SCREEN)
233             PrintString("\n   Screen debugging enabled\n\n");
234
235       if (KdDebugState & KD_DEBUG_BOCHS)
236             PrintString("\n   Bochs debugging enabled\n\n");
237
238       if (KdDebugState & KD_DEBUG_SERIAL)
239             PrintString("\n   Serial debugging enabled. COM%ld %ld Baud\n\n",
240                         LogPortInfo.ComPort, LogPortInfo.BaudRate);
241
242       if (KdDebugState & KD_DEBUG_FILELOG)
243             PrintString("\n   File log debugging enabled\n\n");
244       if (KdDebugState & KD_DEBUG_MDA)
245             PrintString("\n   MDA debugging enabled\n\n");
246     }
247
248   /* Perform any initialization nescessary */
249   if (KdDebuggerEnabled == TRUE)
250     {
251       if (KdDebugState & KD_DEBUG_GDB)
252             KdPortInitializeEx(&GdbPortInfo, 0, 0);
253
254       if (KdDebugState & KD_DEBUG_SERIAL)
255             KdPortInitializeEx(&LogPortInfo, 0, 0);
256
257       if (KdDebugState & KD_DEBUG_FILELOG)
258             DebugLogInit();
259
260       if (KdDebugState & KD_DEBUG_MDA)
261             KdInitializeMda();
262     }
263 }
264
265
266 VOID
267 KdInit1(VOID)
268 {
269   /* Initialize kernel debugger (phase 0) */
270   if ((KdDebuggerEnabled == TRUE) &&
271       (KdDebugState & KD_DEBUG_GDB))
272     {
273       KdGdbStubInit(0);
274     }
275 }
276
277
278 VOID KdInit2(VOID)
279 {
280   /* Initialize kernel debugger (phase 1) */
281   if ((KdDebuggerEnabled == TRUE) &&
282       (KdDebugState & KD_DEBUG_GDB))
283     {
284       KdGdbStubInit(1);
285     }
286 }
287
288 VOID
289 KdSerialDebugPrint (LPSTR Message)
290 {
291   PCHAR pch = (PCHAR) Message;
292
293   while (*pch != 0)
294     {
295       if (*pch == '\n')
296         {
297           KdPortPutByteEx (&LogPortInfo, '\r');
298         }
299         KdPortPutByteEx (&LogPortInfo, *pch);
300         pch++;
301     }
302 }
303
304
305 VOID
306 KdBochsDebugPrint(IN LPSTR  Message)
307 {
308         while (*Message != 0)
309           {
310             if (*Message == '\n')
311               {
312                 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
313               }
314             WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *Message);
315             Message++;
316           }
317 }
318
319
320 ULONG
321 KdpPrintString(PANSI_STRING String)
322 {
323         PCH pch = String->Buffer;
324
325         if (KdDebugState & KD_DEBUG_GDB)
326                 KdGdbDebugPrint(pch);
327
328         if (KdDebugState & KD_DEBUG_SCREEN)
329                 HalDisplayString(pch);
330
331         if (KdDebugState & KD_DEBUG_SERIAL)
332                 KdSerialDebugPrint(pch);
333
334         if (KdDebugState & KD_DEBUG_BOCHS)
335                 KdBochsDebugPrint(pch);
336
337         if (KdDebugState & KD_DEBUG_FILELOG)
338                 DebugLogWrite(pch);
339
340         if (KdDebugState & KD_DEBUG_MDA)
341                 KdPrintMda(pch);
342
343         return((ULONG)String->Length);
344 }
345
346 /* PUBLIC FUNCTIONS *********************************************************/
347
348 /* NTOSKRNL.KdPollBreakIn */
349
350 BOOLEAN STDCALL
351 KdPollBreakIn(VOID)
352 {
353   if ((!KdDebuggerEnabled) || (!(KdDebugState & KD_DEBUG_SERIAL)))
354     return FALSE;
355   return KdpBreakPending;
356 }
357
358 VOID STDCALL
359 KeEnterKernelDebugger(VOID)
360 {
361   HalDisplayString("\n\n *** Entered kernel debugger ***\n");
362
363   for (;;)
364     __asm__("hlt\n\t");
365 }
366
367 VOID STDCALL
368 KdSystemDebugControl(ULONG Code)
369 {
370   extern VOID PsDumpThreads(BOOLEAN IncludeSystem);
371
372   /* A - Dump the entire contents of the non-paged pool. */
373   if (Code == 0)
374     {
375       MiDebugDumpNonPagedPool(FALSE);
376     }
377   /* B - Bug check the system. */
378   else if (Code == 1)
379     {
380       KeBugCheck(0);
381     }
382   /* 
383    * C -  Dump statistics about the distribution of tagged blocks in 
384    *      the non-paged pool.
385    */
386   else if (Code == 2)
387     {
388       MiDebugDumpNonPagedPoolStats(FALSE);
389     }
390   /* 
391    * D - Dump the blocks created in the non-paged pool since the last
392    * SysRq + D and SysRq + E command.
393    */
394   else if (Code == 3)
395     {
396       MiDebugDumpNonPagedPool(TRUE);
397     }
398   /* E - Dump statistics about the tags of newly created blocks. */
399   else if (Code == 4)
400     {
401       MiDebugDumpNonPagedPoolStats(TRUE);
402     }
403   /* F */
404   else if (Code == 5)
405     {
406       PsDumpThreads(TRUE);
407     }
408   /* G */
409   else if (Code == 6)
410     {
411       PsDumpThreads(FALSE);
412     }
413   /* H */
414   else if (Code == 7)
415     {
416     }
417   /* I */
418   else if (Code == 8)
419     {
420     }
421   /* J */
422   else if (Code == 9)
423     {
424     }
425   /* K - Enter the system debugger. */
426   else if (Code == 10)
427     {
428 #ifdef KDBG
429       KdbEnter();
430 #else /* KDBG */
431       DbgPrint("No local kernel debugger\n");
432 #endif /* not KDBG */
433     }
434 }
435
436
437 /* Support routines for the GDB stubs */
438
439 VOID
440 KdPutChar(UCHAR Value)
441 {
442   KdPortPutByteEx (&GdbPortInfo, Value);
443 }
444
445
446 UCHAR
447 KdGetChar(VOID)
448 {
449   UCHAR Value;
450
451   while (!KdPortGetByteEx (&GdbPortInfo, &Value));
452
453   return Value;
454 }
455
456 /* EOF */