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