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