73ca38c260fddfbcac622cd26b8a86544fa87f4d
[reactos.git] / reactos / ntoskrnl / kd / kdebug.c
1 /* $Id: kdebug.c,v 1.22 2001/04/09 02:45:04 dwelch 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
17 /* serial debug connection */
18 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
19 #define DEFAULT_DEBUG_BAUD_RATE 19200 /* 19200 Baud */
20
21 /* bochs debug output */
22 #define BOCHS_LOGGER_PORT (0xe9)
23
24
25 /* TYPEDEFS ****************************************************************/
26
27 #define ScreenDebug (0x1)
28 #define SerialDebug (0x2)
29 #define BochsDebug (0x4)
30 #define FileLogDebug (0x8)
31
32 /* VARIABLES ***************************************************************/
33
34 BOOLEAN
35 __declspec(dllexport)
36 KdDebuggerEnabled = FALSE; /* EXPORTED */
37
38 BOOLEAN
39 __declspec(dllexport)
40 KdDebuggerNotPresent = TRUE; /* EXPORTED */
41
42
43 static BOOLEAN KdpBreakPending = FALSE;
44 static BOOLEAN KdpBreakRecieved = FALSE;
45 static ULONG KdpDebugType = ScreenDebug | BochsDebug;
46
47 /* PRIVATE FUNCTIONS ********************************************************/
48
49 static void
50 PrintString (char* fmt,...)
51 {
52 char buffer[512];
53 va_list ap;
54
55 va_start(ap, fmt);
56 vsprintf(buffer, fmt, ap);
57 va_end(ap);
58
59 HalDisplayString (buffer);
60 }
61
62
63 VOID
64 KdInitSystem (
65 ULONG Reserved,
66 PLOADER_PARAMETER_BLOCK LoaderBlock
67 )
68 {
69 KD_PORT_INFORMATION PortInfo;
70 ULONG Value;
71 PCHAR p1, p2;
72
73 /* set debug port default values */
74 PortInfo.ComPort = DEFAULT_DEBUG_PORT;
75 PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
76
77 /*
78 * parse kernel command line
79 */
80
81 /* check for 'DEBUGPORT' */
82 p1 = (PCHAR)LoaderBlock->CommandLine;
83 while (p1 && (p2 = strchr (p1, '/')))
84 {
85 p2++;
86 if (!_strnicmp (p2, "DEBUGPORT", 9))
87 {
88 p2 += 9;
89 if (*p2 != '=')
90 break;
91 p2++;
92 if (!_strnicmp (p2, "SCREEN", 6))
93 {
94 p2 += 6;
95 KdDebuggerEnabled = TRUE;
96 KdpDebugType |= ScreenDebug;
97 }
98 else if (!_strnicmp (p2, "BOCHS", 5))
99 {
100 p2 += 5;
101 KdDebuggerEnabled = TRUE;
102 KdpDebugType |= BochsDebug;
103 }
104 else if (!_strnicmp (p2, "COM", 3))
105 {
106 p2 += 3;
107 Value = (ULONG)atol (p2);
108 if (Value > 0 && Value < 5)
109 {
110 KdDebuggerEnabled = TRUE;
111 KdpDebugType |= SerialDebug;
112 PortInfo.ComPort = Value;
113 }
114 }
115 break;
116 }
117 p1 = p2;
118 }
119
120
121
122 /* check for 'BAUDRATE' */
123 p1 = (PCHAR)LoaderBlock->CommandLine;
124 while (p1 && (p2 = strchr (p1, '/')))
125 {
126 p2++;
127 if (!_strnicmp (p2, "BAUDRATE", 8))
128 {
129 p2 += 8;
130 if (*p2 != '=')
131 break;
132 p2++;
133 Value = (ULONG)atol (p2);
134 if (Value > 0)
135 {
136 KdDebuggerEnabled = TRUE;
137 KdpDebugType = KdpDebugType | SerialDebug;
138 PortInfo.BaudRate = Value;
139 }
140 break;
141 }
142 p1 = p2;
143 }
144
145 /* Check for 'DEBUG'. Dont' accept 'DEBUGPORT'!*/
146 p1 = (PCHAR)LoaderBlock->CommandLine;
147 while (p1 && (p2 = strchr (p1, '/')))
148 {
149 p2++;
150 if (!_strnicmp (p2, "DEBUG", 5) &&
151 _strnicmp (p2, "DEBUGPORT", 9))
152 {
153 p2 += 5;
154 KdDebuggerEnabled = TRUE;
155 KdpDebugType = KdpDebugType | SerialDebug;
156 break;
157 }
158 p1 = p2;
159 }
160
161 /* Check for 'NODEBUG' */
162 p1 = (PCHAR)LoaderBlock->CommandLine;
163 while (p1 && (p2 = strchr (p1, '/')))
164 {
165 p2++;
166 if (!_strnicmp (p2, "NODEBUG", 7))
167 {
168 p2 += 7;
169 KdDebuggerEnabled = FALSE;
170 break;
171 }
172 p1 = p2;
173 }
174
175 /* Check for 'CRASHDEBUG' */
176 p1 = (PCHAR)LoaderBlock->CommandLine;
177 while (p1 && (p2 = strchr (p1, '/')))
178 {
179 p2++;
180 if (!_strnicmp (p2, "CRASHDEBUG", 10))
181 {
182 p2 += 10;
183 KdDebuggerEnabled = FALSE;
184 break;
185 }
186 p1 = p2;
187 }
188
189 /* Check for 'BREAK' */
190 p1 = (PCHAR)LoaderBlock->CommandLine;
191 while (p1 && (p2 = strchr (p1, '/')))
192 {
193 p2++;
194 if (!_strnicmp (p2, "BREAK", 5))
195 {
196 p2 += 7;
197 KdpBreakPending = TRUE;
198 break;
199 }
200 p1 = p2;
201 }
202
203 #ifdef DBGPRINT_FILE_LOG
204 KdpDebugType |= FileLogDebug;
205 DebugLogInit();
206 #endif /* DBGPRINT_FILE_LOG */
207
208 /* print some information */
209 if (KdDebuggerEnabled == TRUE)
210 {
211 if (KdpDebugType & ScreenDebug)
212 {
213 PrintString ("\n Screen debugging enabled\n\n");
214 }
215 if (KdpDebugType & BochsDebug)
216 {
217 PrintString ("\n Bochs debugging enabled\n\n");
218 }
219 if (KdpDebugType & SerialDebug)
220 {
221 PrintString ("\n Serial debugging enabled: COM%ld %ld Baud\n\n",
222 PortInfo.ComPort, PortInfo.BaudRate);
223 }
224 if (KdpDebugType & FileLogDebug)
225 {
226 PrintString("\n File log debugging enabled\n\n");
227 }
228 }
229 else
230 PrintString ("\n Debugging disabled\n\n");
231
232
233 /* initialize debug port */
234 if (KdDebuggerEnabled && (KdpDebugType & SerialDebug))
235 {
236 KdPortInitialize (&PortInfo,
237 0,
238 0);
239 }
240 }
241
242
243 ULONG KdpPrintString (PANSI_STRING String)
244 {
245 PCH pch = String->Buffer;
246
247 if (KdpDebugType & ScreenDebug)
248 {
249 HalDisplayString (String->Buffer);
250 }
251 if (KdpDebugType & SerialDebug)
252 {
253 while (*pch != 0)
254 {
255 if (*pch == '\n')
256 {
257 KdPortPutByte ('\r');
258 }
259 KdPortPutByte (*pch);
260 pch++;
261 }
262 }
263 if (KdpDebugType & BochsDebug)
264 {
265 while (*pch != 0)
266 {
267 if (*pch == '\n')
268 {
269 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
270 }
271 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *pch);
272 pch++;
273 }
274 }
275 #ifdef DBGPRINT_FILE_LOG
276 if (KdpDebugType & FileLogDebug)
277 {
278 DebugLogWrite(String->Buffer);
279 }
280 #endif /* DBGPRINT_FILE_LOG */
281 return (ULONG)String->Length;
282 }
283
284 /* PUBLIC FUNCTIONS *********************************************************/
285
286 /* NTOSKRNL.KdPollBreakIn */
287
288 BOOLEAN
289 STDCALL
290 KdPollBreakIn (
291 VOID
292 )
293 {
294 BOOLEAN Result = FALSE;
295 UCHAR ByteRead;
296
297 if (KdDebuggerEnabled == FALSE || KdpDebugType != SerialDebug)
298 return Result;
299
300 // Flags = KiDisableInterrupts();
301
302 HalDisplayString ("Waiting for kernel debugger connection...\n");
303
304 if (KdPortPollByte (&ByteRead))
305 {
306 if (ByteRead == 0x62)
307 {
308 if (KdpBreakPending == TRUE)
309 {
310 KdpBreakPending = FALSE;
311 KdpBreakRecieved = TRUE;
312 Result = TRUE;
313 }
314 HalDisplayString (" Kernel debugger connected\n");
315 }
316 else
317 {
318 HalDisplayString (" Kernel debugger connection failed\n");
319 }
320 }
321
322 // KiRestoreInterrupts (Flags);
323
324 return Result;
325 }
326
327 VOID STDCALL
328 KeEnterKernelDebugger (VOID)
329 {
330 HalDisplayString ("\n\n *** Entered kernel debugger ***\n");
331
332 #if 1
333 for (;;)
334 __asm__("hlt\n\t");
335 #else
336 for(;;);
337 #endif
338 }
339
340 VOID STDCALL
341 KdSystemDebugControl(ULONG Code)
342 {
343 /* A - Dump the entire contents of the non-paged pool. */
344 if (Code == 0)
345 {
346 MiDebugDumpNonPagedPool(FALSE);
347 }
348 /* B - Bug check the system. */
349 else if (Code == 1)
350 {
351 KeBugCheck(0);
352 }
353 /*
354 * C - Dump statistics about the distribution of tagged blocks in
355 * the non-paged pool.
356 */
357 else if (Code == 2)
358 {
359 MiDebugDumpNonPagedPoolStats(FALSE);
360 }
361 /*
362 * D - Dump the blocks created in the non-paged pool since the last
363 * SysRq + D and SysRq + E command.
364 */
365 else if (Code == 3)
366 {
367 MiDebugDumpNonPagedPool(TRUE);
368 }
369 /* E - Dump statistics about the tags of newly created blocks. */
370 else if (Code == 4)
371 {
372 MiDebugDumpNonPagedPoolStats(TRUE);
373 }
374 /* F */
375 else if (Code == 5)
376 {
377 }
378 /* G */
379 else if (Code == 6)
380 {
381 }
382 /* H */
383 else if (Code == 7)
384 {
385 }
386 /* I */
387 else if (Code == 8)
388 {
389 }
390 /* J */
391 else if (Code == 9)
392 {
393 }
394 /* K - Enter the system debugger. */
395 else if (Code == 10)
396 {
397 #if KDBG
398 #else /* KDBG */
399 #endif /* not KDBG */
400 }
401 }
402
403 /* EOF */