7f0417b7ff0757726028ce1b41817c12ae9e466e
[reactos.git] / reactos / ntoskrnl / kd / kdebug.c
1 /* $Id: kdebug.c,v 1.34 2002/02/09 18:41:24 chorns Exp $
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 DEBUG_TYPE KdDebugType = NoDebug;
41 ULONG KdpPortIrq = 0;
42
43 /* PRIVATE FUNCTIONS ********************************************************/
44
45 static VOID
46 PrintString(char* fmt,...)
47 {
48 char buffer[512];
49 va_list ap;
50
51 va_start(ap, fmt);
52 vsprintf(buffer, fmt, ap);
53 va_end(ap);
54
55 HalDisplayString(buffer);
56 }
57
58
59 VOID
60 KdInitSystem(ULONG Reserved,
61 PLOADER_PARAMETER_BLOCK LoaderBlock)
62 {
63 KD_PORT_INFORMATION PortInfo;
64 ULONG Value;
65 PCHAR p1, p2;
66
67 #ifdef KDBG
68 /* Initialize runtime debugging if available */
69 DbgRDebugInit();
70 #endif
71
72 /* set debug port default values */
73 PortInfo.ComPort = DEFAULT_DEBUG_PORT;
74 PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
75 KdpPortIrq = DEFAULT_DEBUG_COM2_IRQ;
76
77 /* parse kernel command line */
78
79 /* check for 'DEBUGPORT' */
80 p1 = (PCHAR)LoaderBlock->CommandLine;
81 while (p1 && (p2 = strchr(p1, '/')))
82 {
83 p2++;
84 if (!_strnicmp(p2, "DEBUGPORT", 9))
85 {
86 p2 += 9;
87 if (*p2 == '=')
88 {
89 p2++;
90 if (!_strnicmp(p2, "SCREEN", 6))
91 {
92 p2 += 6;
93 KdDebuggerEnabled = TRUE;
94 KdDebugType = ScreenDebug;
95 }
96 else if (!_strnicmp(p2, "BOCHS", 5))
97 {
98 p2 += 5;
99 KdDebuggerEnabled = TRUE;
100 KdDebugType = BochsDebug;
101 }
102 else if (!_strnicmp(p2, "GDB", 3))
103 {
104 p2 += 3;
105 KdDebuggerEnabled = TRUE;
106 KdDebugType = GdbDebug;
107 }
108 else if (!_strnicmp(p2, "PICE", 4))
109 {
110 p2 += 4;
111 KdDebuggerEnabled = TRUE;
112 KdDebugType = PiceDebug;
113 }
114 else if (!_strnicmp(p2, "COM", 3))
115 {
116 p2 += 3;
117 Value = (ULONG)atol(p2);
118 if (Value > 0 && Value < 5)
119 {
120 PrintString("\n COM2 found\n\n");
121 KdDebuggerEnabled = TRUE;
122 KdDebugType = SerialDebug;
123 PortInfo.ComPort = Value;
124 }
125 }
126 else if (!_strnicmp(p2, "FILE", 4))
127 {
128 p2 += 4;
129 KdDebuggerEnabled = TRUE;
130 KdDebugType = FileLogDebug;
131 }
132 }
133 }
134 else if (!_strnicmp(p2, "DEBUG", 5))
135 {
136 p2 += 5;
137 /* Check that KdDebugType equals NoDebug so we don't override any set KdDebugType */
138 if (KdDebugType == NoDebug)
139 {
140 KdDebuggerEnabled = TRUE;
141 KdDebugType = SerialDebug;
142 }
143 }
144 else if (!_strnicmp(p2, "NODEBUG", 7))
145 {
146 p2 += 7;
147 KdDebuggerEnabled = FALSE;
148 KdDebugType = NoDebug;
149 }
150 else if (!_strnicmp(p2, "CRASHDEBUG", 10))
151 {
152 p2 += 10;
153 KdDebuggerEnabled = FALSE;
154 KdDebugType = NoDebug;
155 }
156 else if (!_strnicmp(p2, "BREAK", 5))
157 {
158 p2 += 5;
159 KdpBreakPending = TRUE;
160 }
161 else if (!_strnicmp(p2, "BAUDRATE", 8))
162 {
163 p2 += 8;
164 if (*p2 != '=')
165 {
166 p2++;
167 Value = (ULONG)atol(p2);
168 if (Value > 0)
169 {
170 KdDebuggerEnabled = TRUE;
171 KdDebugType = SerialDebug;
172 PortInfo.BaudRate = Value;
173 }
174 }
175 else if (!_strnicmp(p2, "IRQ", 3))
176 {
177 p2 += 3;
178 if (*p2 != '=')
179 {
180 p2++;
181 Value = (ULONG)atol(p2);
182 if (Value > 0)
183 {
184 KdDebuggerEnabled = TRUE;
185 KdDebugType = SerialDebug;
186 KdpPortIrq = Value;
187 }
188 }
189 }
190 }
191 p1 = p2;
192 }
193
194 /* print some information */
195 if (KdDebuggerEnabled == TRUE)
196 {
197 switch (KdDebugType)
198 {
199 case NoDebug:
200 break;
201
202 case GdbDebug:
203 PrintString("\n GDB debugging enabled\n\n");
204 break;
205
206 case PiceDebug:
207 PrintString("\n Private ICE debugger enabled\n\n");
208 break;
209
210 case ScreenDebug:
211 //PrintString("\n Screen debugging enabled\n\n");
212 break;
213
214 case BochsDebug:
215 PrintString("\n Bochs debugging enabled\n\n");
216 break;
217
218 case SerialDebug:
219 PrintString("\n Serial debugging enabled: COM%ld %ld Baud\n\n",
220 PortInfo.ComPort, PortInfo.BaudRate);
221 break;
222
223 case FileLogDebug:
224 PrintString("\n File log debugging enabled\n\n");
225 break;
226 }
227 }
228
229 /* initialize debug port */
230 if (KdDebuggerEnabled == TRUE)
231 {
232 switch (KdDebugType)
233 {
234 case SerialDebug:
235 case GdbDebug:
236 KdPortInitialize(&PortInfo,
237 0,
238 0);
239 break;
240
241 case FileLogDebug:
242 DebugLogInit();
243 break;
244
245 default:
246 break;
247 }
248 }
249 }
250
251
252 VOID
253 KdInit1(VOID)
254 {
255 /* Initialize kernel debugger */
256 if (KdDebuggerEnabled == TRUE &&
257 KdDebugType == GdbDebug)
258 {
259 KdGdbStubInit(0);
260 }
261 }
262
263
264 VOID KdInit2(VOID)
265 {
266 if (KdDebuggerEnabled == TRUE &&
267 KdDebugType == GdbDebug)
268 {
269 KdGdbStubInit(1);
270 }
271 }
272
273 VOID
274 KdDebugPrint (LPSTR Message)
275 {
276 PCHAR pch = (PCHAR) Message;
277
278 while (*pch != 0)
279 {
280 if (*pch == '\n')
281 {
282 KdPortPutByte ('\r');
283 }
284 KdPortPutByte (*pch);
285 pch++;
286 }
287 }
288
289 ULONG
290 KdpPrintString(PANSI_STRING String)
291 {
292 PCH pch = String->Buffer;
293
294 switch (KdDebugType)
295 {
296 case NoDebug:
297 break;
298
299 case GdbDebug:
300 KdGdbDebugPrint(pch);
301 break;
302
303 case PiceDebug:
304 break;
305
306 case ScreenDebug:
307 HalDisplayString(pch);
308 break;
309
310 case SerialDebug:
311 KdDebugPrint(pch);
312 break;
313
314 case BochsDebug:
315 while (*pch != 0)
316 {
317 if (*pch == '\n')
318 {
319 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
320 }
321 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *pch);
322 pch++;
323 }
324 break;
325
326 case FileLogDebug:
327 DebugLogWrite(pch);
328 break;
329 }
330
331 return((ULONG)String->Length);
332 }
333
334 /* PUBLIC FUNCTIONS *********************************************************/
335
336 /* NTOSKRNL.KdPollBreakIn */
337
338 BOOLEAN STDCALL
339 KdPollBreakIn(VOID)
340 {
341 if ((!KdDebuggerEnabled) || (KdDebugType != SerialDebug))
342 return FALSE;
343 return KdpBreakPending;
344 }
345
346 VOID STDCALL
347 KeEnterKernelDebugger(VOID)
348 {
349 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
350
351 for (;;)
352 __asm__("hlt\n\t");
353 }
354
355 VOID STDCALL
356 KdSystemDebugControl(ULONG Code)
357 {
358 extern VOID PsDumpThreads(BOOLEAN IncludeSystem);
359
360 /* A - Dump the entire contents of the non-paged pool. */
361 if (Code == 0)
362 {
363 MiDebugDumpNonPagedPool(FALSE);
364 }
365 /* B - Bug check the system. */
366 else if (Code == 1)
367 {
368 KeBugCheck(0);
369 }
370 /*
371 * C - Dump statistics about the distribution of tagged blocks in
372 * the non-paged pool.
373 */
374 else if (Code == 2)
375 {
376 MiDebugDumpNonPagedPoolStats(FALSE);
377 }
378 /*
379 * D - Dump the blocks created in the non-paged pool since the last
380 * SysRq + D and SysRq + E command.
381 */
382 else if (Code == 3)
383 {
384 MiDebugDumpNonPagedPool(TRUE);
385 }
386 /* E - Dump statistics about the tags of newly created blocks. */
387 else if (Code == 4)
388 {
389 MiDebugDumpNonPagedPoolStats(TRUE);
390 }
391 /* F */
392 else if (Code == 5)
393 {
394 PsDumpThreads(TRUE);
395 }
396 /* G */
397 else if (Code == 6)
398 {
399 PsDumpThreads(FALSE);
400 }
401 /* H */
402 else if (Code == 7)
403 {
404 }
405 /* I */
406 else if (Code == 8)
407 {
408 }
409 /* J */
410 else if (Code == 9)
411 {
412 }
413 /* K - Enter the system debugger. */
414 else if (Code == 10)
415 {
416 #ifdef KDBG
417 KdbEnter();
418 #else /* KDBG */
419 DbgPrint("No local kernel debugger\n");
420 #endif /* not KDBG */
421 }
422 }
423
424
425 /* Support routines for the GDB stubs */
426
427 VOID
428 KdPutChar(UCHAR Value)
429 {
430 KdPortPutByte (Value);
431 }
432
433
434 UCHAR
435 KdGetChar(VOID)
436 {
437 UCHAR Value;
438
439 while (!KdPortGetByte (&Value));
440
441 return Value;
442 }
443
444 /* EOF */