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