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