[CLT2012]
[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 #if defined (ALLOC_PRAGMA)
15 #pragma alloc_text(INIT, KdInitSystem)
16 #endif
17
18
19 /* Make bochs debug output in the very early boot phase available */
20 //#define AUTO_ENABLE_BOCHS
21
22 /* VARIABLES ***************************************************************/
23
24 KD_PORT_INFORMATION PortInfo = {DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0};
25 ULONG KdpPortIrq;
26 #ifdef AUTO_ENABLE_BOCHS
27 KDP_DEBUG_MODE KdpDebugMode = {{{.Bochs=TRUE}}};
28 #else
29 KDP_DEBUG_MODE KdpDebugMode;
30 #endif
31 PKDP_INIT_ROUTINE WrapperInitRoutine;
32 KD_DISPATCH_TABLE WrapperTable;
33 BOOLEAN KdpEarlyBreak = FALSE;
34 LIST_ENTRY KdProviders = {&KdProviders, &KdProviders};
35 KD_DISPATCH_TABLE DispatchTable[KdMax];
36
37 PKDP_INIT_ROUTINE InitRoutines[KdMax] = {KdpScreenInit,
38 KdpSerialInit,
39 KdpInitDebugLog,
40 KdpBochsInit,
41 KdpKdbgInit};
42
43 extern ANSI_STRING KdpLogFileName;
44
45 /* PRIVATE FUNCTIONS *********************************************************/
46
47 PCHAR
48 NTAPI
49 INIT_FUNCTION
50 KdpGetDebugMode(PCHAR Currentp2)
51 {
52 PCHAR p1, p2 = Currentp2;
53 ULONG Value;
54
55 /* Check for Screen Debugging */
56 if (!_strnicmp(p2, "SCREEN", 6))
57 {
58 /* Enable It */
59 p2 += 6;
60 KdpDebugMode.Screen = TRUE;
61 }
62 /* Check for Serial Debugging */
63 else if (!_strnicmp(p2, "COM", 3))
64 {
65 /* Gheck for a valid Serial Port */
66 p2 += 3;
67 if (*p2 != ':')
68 {
69 Value = (ULONG)atol(p2);
70 if (Value > 0 && Value < 5)
71 {
72 /* Valid port found, enable Serial Debugging */
73 KdpDebugMode.Serial = TRUE;
74
75 /* Set the port to use */
76 SerialPortInfo.ComPort = Value;
77 KdpPort = Value;
78 }
79 }
80 else
81 {
82 Value = strtoul(p2 + 1, NULL, 0);
83 if (Value)
84 {
85 KdpDebugMode.Serial = TRUE;
86 SerialPortInfo.BaseAddress = Value;
87 SerialPortInfo.ComPort = 0;
88 KdpPort = 0;
89 }
90 }
91 }
92
93 /* Check for Debug Log Debugging */
94 else if (!_strnicmp(p2, "FILE", 4))
95 {
96 /* Enable It */
97 p2 += 4;
98 KdpDebugMode.File = TRUE;
99 if (*p2 == ':')
100 {
101 p2++;
102 p1 = p2;
103 while (*p2 != '\0' && *p2 != ' ') p2++;
104 KdpLogFileName.MaximumLength = KdpLogFileName.Length = p2 - p1;
105 KdpLogFileName.Buffer = p1;
106 }
107 }
108
109 /* Check for BOCHS Debugging */
110 else if (!_strnicmp(p2, "BOCHS", 5))
111 {
112 /* Enable It */
113 p2 += 5;
114 KdpDebugMode.Bochs = TRUE;
115 }
116
117 /* Check for GDB Debugging */
118 else if (!_strnicmp(p2, "GDB", 3))
119 {
120 /* Enable it */
121 p2 += 3;
122 KdpDebugMode.Gdb = TRUE;
123
124 /* Enable Debugging */
125 KdDebuggerEnabled = TRUE;
126 KdDebuggerNotPresent = FALSE;
127 WrapperInitRoutine = KdpGdbStubInit;
128 }
129
130 /* Check for PICE Debugging */
131 else if (!_strnicmp(p2, "PICE", 4))
132 {
133 /* Enable it */
134 p2 += 4;
135 KdpDebugMode.Pice = TRUE;
136
137 /* Enable Debugging */
138 KdDebuggerEnabled = TRUE;
139 KdDebuggerNotPresent = FALSE;
140 }
141
142 return p2;
143 }
144
145 VOID
146 NTAPI
147 INIT_FUNCTION
148 KdpCallInitRoutine(ULONG BootPhase)
149 {
150 PLIST_ENTRY CurrentEntry;
151 PKD_DISPATCH_TABLE CurrentTable;
152
153 /* Call the registered handlers */
154 CurrentEntry = KdProviders.Flink;
155 while (CurrentEntry != &KdProviders)
156 {
157 /* Get the current table */
158 CurrentTable = CONTAINING_RECORD(CurrentEntry,
159 KD_DISPATCH_TABLE,
160 KdProvidersList);
161
162 /* Call it */
163 CurrentTable->KdpInitRoutine(CurrentTable, BootPhase);
164
165 /* Next Table */
166 CurrentEntry = CurrentEntry->Flink;
167 }
168
169 /* Call the Wrapper Init Routine */
170 if (WrapperInitRoutine)
171 WrapperTable.KdpInitRoutine(&WrapperTable, BootPhase);
172 }
173
174 BOOLEAN
175 INIT_FUNCTION
176 NTAPI
177 KdInitSystem(ULONG BootPhase,
178 PLOADER_PARAMETER_BLOCK LoaderBlock)
179 {
180 ULONG Value;
181 ULONG i;
182 PCHAR CommandLine, Port, BaudRate, Irq;
183
184 /* Set Default Port Options */
185 if (BootPhase == 0)
186 {
187 /* Get the Command Line */
188 CommandLine = LoaderBlock->LoadOptions;
189
190 /* Upcase it */
191 _strupr(CommandLine);
192
193 /* XXX Check for settings that we support */
194 if (strstr(CommandLine, "BREAK")) KdpEarlyBreak = TRUE;
195 if (strstr(CommandLine, "NODEBUG")) KdDebuggerEnabled = FALSE;
196 else if (strstr(CommandLine, "CRASHDEBUG")) KdDebuggerEnabled = FALSE;
197 else if (strstr(CommandLine, "DEBUG"))
198 {
199 /* Enable the kernel debugger */
200 KdDebuggerEnabled = TRUE;
201 KdDebuggerNotPresent = FALSE;
202 #ifdef KDBG
203 /* Get the KDBG Settings */
204 KdbpGetCommandLineSettings(LoaderBlock->LoadOptions);
205 #endif
206 }
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 */