3a7071d5cb379e3ebdf7d197b0836c9cf70f9eea
[reactos.git] / ntoskrnl / kd / kdinit.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <debug.h>
13
14 /* Make bochs debug output in the very early boot phase available */
15 //#define AUTO_ENABLE_BOCHS
16
17 /* VARIABLES ***************************************************************/
18
19 ULONG PortNumber = DEFAULT_DEBUG_PORT;
20 CPPORT PortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
21 ULONG KdpPortIrq;
22 #ifdef AUTO_ENABLE_BOCHS
23 KDP_DEBUG_MODE KdpDebugMode = {{{.Bochs=TRUE}}};
24 #else
25 KDP_DEBUG_MODE KdpDebugMode;
26 #endif
27 PKDP_INIT_ROUTINE WrapperInitRoutine;
28 KD_DISPATCH_TABLE WrapperTable;
29 LIST_ENTRY KdProviders = {&KdProviders, &KdProviders};
30 KD_DISPATCH_TABLE DispatchTable[KdMax];
31
32 PKDP_INIT_ROUTINE InitRoutines[KdMax] = {KdpScreenInit,
33 KdpSerialInit,
34 KdpInitDebugLog,
35 KdpBochsInit,
36 KdpKdbgInit};
37
38 extern ANSI_STRING KdpLogFileName;
39
40 /* PRIVATE FUNCTIONS *********************************************************/
41
42 PCHAR
43 NTAPI
44 INIT_FUNCTION
45 KdpGetDebugMode(PCHAR Currentp2)
46 {
47 PCHAR p1, p2 = Currentp2;
48 ULONG Value;
49
50 /* Check for Screen Debugging */
51 if (!_strnicmp(p2, "SCREEN", 6))
52 {
53 /* Enable It */
54 p2 += 6;
55 KdpDebugMode.Screen = TRUE;
56 }
57 /* Check for Serial Debugging */
58 else if (!_strnicmp(p2, "COM", 3))
59 {
60 /* Gheck for a valid Serial Port */
61 p2 += 3;
62 if (*p2 != ':')
63 {
64 Value = (ULONG)atol(p2);
65 if (Value > 0 && Value < 5)
66 {
67 /* Valid port found, enable Serial Debugging */
68 KdpDebugMode.Serial = TRUE;
69
70 /* Set the port to use */
71 SerialPortNumber = Value;
72 KdpPort = Value;
73 }
74 }
75 else
76 {
77 Value = strtoul(p2 + 1, NULL, 0);
78 if (Value)
79 {
80 KdpDebugMode.Serial = TRUE;
81 SerialPortInfo.Address = UlongToPtr(Value);
82 SerialPortNumber = 0;
83 KdpPort = 0;
84 }
85 }
86 }
87
88 /* Check for Debug Log Debugging */
89 else if (!_strnicmp(p2, "FILE", 4))
90 {
91 /* Enable It */
92 p2 += 4;
93 KdpDebugMode.File = TRUE;
94 if (*p2 == ':')
95 {
96 p2++;
97 p1 = p2;
98 while (*p2 != '\0' && *p2 != ' ') p2++;
99 KdpLogFileName.MaximumLength = KdpLogFileName.Length = p2 - p1;
100 KdpLogFileName.Buffer = p1;
101 }
102 }
103
104 /* Check for BOCHS Debugging */
105 else if (!_strnicmp(p2, "BOCHS", 5))
106 {
107 /* Enable It */
108 p2 += 5;
109 KdpDebugMode.Bochs = TRUE;
110 }
111
112 /* Check for GDB Debugging */
113 else if (!_strnicmp(p2, "GDB", 3))
114 {
115 /* Enable it */
116 p2 += 3;
117 KdpDebugMode.Gdb = TRUE;
118
119 /* Enable Debugging */
120 KdDebuggerNotPresent = FALSE;
121 KdDebuggerEnabled = TRUE;
122 SharedUserData->KdDebuggerEnabled = TRUE;
123 WrapperInitRoutine = KdpGdbStubInit;
124 }
125
126 /* Check for PICE Debugging */
127 else if (!_strnicmp(p2, "PICE", 4))
128 {
129 /* Enable it */
130 p2 += 4;
131 KdpDebugMode.Pice = TRUE;
132
133 /* Enable Debugging */
134 KdDebuggerNotPresent = FALSE;
135 KdDebuggerEnabled = TRUE;
136 SharedUserData->KdDebuggerEnabled = TRUE;
137 }
138
139 return p2;
140 }
141
142 VOID
143 NTAPI
144 INIT_FUNCTION
145 KdpCallInitRoutine(ULONG BootPhase)
146 {
147 PLIST_ENTRY CurrentEntry;
148 PKD_DISPATCH_TABLE CurrentTable;
149
150 /* Call the registered handlers */
151 CurrentEntry = KdProviders.Flink;
152 while (CurrentEntry != &KdProviders)
153 {
154 /* Get the current table */
155 CurrentTable = CONTAINING_RECORD(CurrentEntry,
156 KD_DISPATCH_TABLE,
157 KdProvidersList);
158
159 /* Call it */
160 CurrentTable->KdpInitRoutine(CurrentTable, BootPhase);
161
162 /* Next Table */
163 CurrentEntry = CurrentEntry->Flink;
164 }
165
166 /* Call the Wrapper Init Routine */
167 if (WrapperInitRoutine)
168 WrapperTable.KdpInitRoutine(&WrapperTable, BootPhase);
169 }
170
171 BOOLEAN
172 NTAPI
173 KdInitSystem(ULONG BootPhase,
174 PLOADER_PARAMETER_BLOCK LoaderBlock)
175 {
176 ULONG Value;
177 ULONG i;
178 PCHAR CommandLine, Port, BaudRate, Irq;
179
180 /* Set Default Port Options */
181 if (BootPhase == 0)
182 {
183 /* Get the Command Line */
184 CommandLine = LoaderBlock->LoadOptions;
185
186 /* Upcase it */
187 _strupr(CommandLine);
188
189 /* XXX Check for settings that we support */
190 if (strstr(CommandLine, "NODEBUG")) KdDebuggerEnabled = FALSE;
191 else if (strstr(CommandLine, "CRASHDEBUG")) KdDebuggerEnabled = FALSE;
192 else if (strstr(CommandLine, "DEBUG"))
193 {
194 /* Enable the kernel debugger */
195 KdDebuggerNotPresent = FALSE;
196 KdDebuggerEnabled = TRUE;
197 #ifdef KDBG
198 /* Get the KDBG Settings */
199 KdbpGetCommandLineSettings(LoaderBlock->LoadOptions);
200 #endif
201 }
202
203 /* Let user-mode know our state */
204 SharedUserData->KdDebuggerEnabled = KdDebuggerEnabled;
205
206 /* Get the port and baud rate */
207 Port = strstr(CommandLine, "DEBUGPORT");
208 BaudRate = strstr(CommandLine, "BAUDRATE");
209 Irq = strstr(CommandLine, "IRQ");
210
211 /* Check if we got the /DEBUGPORT parameter(s) */
212 while (Port)
213 {
214 /* Move past the actual string, to reach the port*/
215 Port += sizeof("DEBUGPORT") - 1;
216
217 /* Now get past any spaces and skip the equal sign */
218 while (*Port == ' ') Port++;
219 Port++;
220
221 /* Get the debug mode and wrapper */
222 Port = KdpGetDebugMode(Port);
223 Port = strstr(Port, "DEBUGPORT");
224 }
225
226 /* Use serial port then */
227 if (KdDebuggerEnabled && KdpDebugMode.Value == 0)
228 KdpDebugMode.Serial = TRUE;
229
230 /* Check if we got a baud rate */
231 if (BaudRate)
232 {
233 /* Move past the actual string, to reach the rate */
234 BaudRate += sizeof("BAUDRATE") - 1;
235
236 /* Now get past any spaces */
237 while (*BaudRate == ' ') BaudRate++;
238
239 /* And make sure we have a rate */
240 if (*BaudRate)
241 {
242 /* Read and set it */
243 Value = atol(BaudRate + 1);
244 if (Value) PortInfo.BaudRate = SerialPortInfo.BaudRate = Value;
245 }
246 }
247
248 /* Check Serial Port Settings [IRQ] */
249 if (Irq)
250 {
251 /* Move past the actual string, to reach the rate */
252 Irq += sizeof("IRQ") - 1;
253
254 /* Now get past any spaces */
255 while (*Irq == ' ') Irq++;
256
257 /* And make sure we have an IRQ */
258 if (*Irq)
259 {
260 /* Read and set it */
261 Value = atol(Irq + 1);
262 if (Value) KdpPortIrq = Value;
263 }
264 }
265
266 /* Call Providers at Phase 0 */
267 for (i = 0; i < KdMax; i++)
268 {
269 InitRoutines[i](&DispatchTable[i], 0);
270 }
271
272 /* Call Wrapper at Phase 0 */
273 if (WrapperInitRoutine) WrapperInitRoutine(&WrapperTable, 0);
274 return TRUE;
275 }
276 else /* BootPhase > 0 */
277 {
278 #ifdef _M_IX86
279 KdpEnableSafeMem();
280 #endif
281 }
282
283 /* Call the Initialization Routines of the Registered Providers */
284 KdpCallInitRoutine(BootPhase);
285
286 /* Return success */
287 return TRUE;
288 }
289
290 /* EOF */