Replaced boot_param by LOADER_PARAMETER_BLOCK
[reactos.git] / reactos / ntoskrnl / kd / kdebug.c
1 /* $Id: kdebug.c,v 1.12 2000/07/01 18:25:00 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 <stdlib.h>
16 #include <ctype.h>
17
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
33 /* VARIABLES ***************************************************************/
34
35 BOOLEAN
36 __declspec(dllexport)
37 KdDebuggerEnabled = FALSE; /* EXPORTED */
38
39 BOOLEAN
40 __declspec(dllexport)
41 KdDebuggerNotPresent = TRUE; /* EXPORTED */
42
43
44 static BOOLEAN KdpBreakPending = FALSE;
45 static BOOLEAN KdpBreakRecieved = FALSE;
46 static ULONG KdpDebugType = BochsDebug;
47
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 /* set debug port default values */
76 PortInfo.ComPort = DEFAULT_DEBUG_PORT;
77 PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE;
78
79 /*
80 * parse kernel command line
81 */
82
83 /* check for 'DEBUGPORT' */
84 p1 = LoaderBlock->kernel_parameters;
85 while (p1 && (p2 = strchr (p1, '/')))
86 {
87 p2++;
88 if (!_strnicmp (p2, "DEBUGPORT", 9))
89 {
90 p2 += 9;
91 if (*p2 != '=')
92 break;
93 p2++;
94 if (!_strnicmp (p2, "SCREEN", 6))
95 {
96 p2 += 6;
97 KdDebuggerEnabled = TRUE;
98 KdpDebugType |= ScreenDebug;
99 }
100 else if (!_strnicmp (p2, "BOCHS", 5))
101 {
102 p2 += 5;
103 KdDebuggerEnabled = TRUE;
104 KdpDebugType |= BochsDebug;
105 }
106 else if (!_strnicmp (p2, "COM", 3))
107 {
108 p2 += 3;
109 Value = (ULONG)atol (p2);
110 if (Value > 0 && Value < 5)
111 {
112 KdDebuggerEnabled = TRUE;
113 KdpDebugType |= SerialDebug;
114 PortInfo.ComPort = Value;
115 }
116 }
117 break;
118 }
119 p1 = p2;
120 }
121
122 /* check for 'BAUDRATE' */
123 p1 = LoaderBlock->kernel_parameters;
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 = LoaderBlock->kernel_parameters;
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 = LoaderBlock->kernel_parameters;
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 = LoaderBlock->kernel_parameters;
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 = LoaderBlock->kernel_parameters;
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
204 /* print some information */
205 if (KdDebuggerEnabled == TRUE)
206 {
207 if (KdpDebugType & ScreenDebug)
208 {
209 PrintString ("\n Screen debugging enabled\n\n");
210 }
211 if (KdpDebugType & BochsDebug)
212 {
213 PrintString ("\n Bochs debugging enabled\n\n");
214 }
215 if (KdpDebugType & SerialDebug)
216 {
217 PrintString ("\n Serial debugging enabled: COM%ld %ld Baud\n\n",
218 PortInfo.ComPort, PortInfo.BaudRate);
219 }
220 }
221 else
222 PrintString ("\n Debugging disabled\n\n");
223
224
225 /* initialize debug port */
226 if (KdDebuggerEnabled && KdpDebugType == SerialDebug)
227 {
228 KdPortInitialize (&PortInfo,
229 0,
230 0);
231 }
232 }
233
234
235 ULONG KdpPrintString (PANSI_STRING String)
236 {
237 PCH pch = String->Buffer;
238
239 if (KdpDebugType & ScreenDebug)
240 {
241 HalDisplayString (String->Buffer);
242 }
243 if (KdpDebugType & SerialDebug)
244 {
245 while (*pch != 0)
246 {
247 if (*pch == '\n')
248 {
249 KdPortPutByte ('\r');
250 }
251 KdPortPutByte (*pch);
252 pch++;
253 }
254 }
255 if (KdpDebugType & BochsDebug)
256 {
257 while (*pch != 0)
258 {
259 if (*pch == '\n')
260 {
261 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r');
262 }
263 WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *pch);
264 pch++;
265 }
266 }
267
268 return (ULONG)String->Length;
269 }
270
271 /* PUBLIC FUNCTIONS *********************************************************/
272
273 /* NTOSKRNL.KdPollBreakIn */
274
275 BOOLEAN
276 STDCALL
277 KdPollBreakIn (
278 VOID
279 )
280 {
281 BOOLEAN Result = FALSE;
282 UCHAR ByteRead;
283
284 if (KdDebuggerEnabled == FALSE || KdpDebugType != SerialDebug)
285 return Result;
286
287 // Flags = KiDisableInterrupts();
288
289 HalDisplayString ("Waiting for kernel debugger connection...\n");
290
291 if (KdPortPollByte (&ByteRead))
292 {
293 if (ByteRead == 0x62)
294 {
295 if (KdpBreakPending == TRUE)
296 {
297 KdpBreakPending = FALSE;
298 KdpBreakRecieved = TRUE;
299 Result = TRUE;
300 }
301 HalDisplayString (" Kernel debugger connected\n");
302 }
303 else
304 {
305 HalDisplayString (" Kernel debugger connection failed\n");
306 }
307 }
308
309 // KiRestoreInterrupts (Flags);
310
311 return Result;
312 }
313
314 VOID
315 STDCALL
316 KeEnterKernelDebugger (
317 VOID
318 )
319 {
320 HalDisplayString ("\n\n *** Entered kernel debugger ***\n");
321
322 for (;;)
323 __asm__("hlt\n\t");
324 }
325
326 /* EOF */