[NTOSKRNL]
[reactos.git] / reactos / 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 KD_PORT_INFORMATION PortInfo = {DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0};
20 ULONG KdpPortIrq;
21 #ifdef AUTO_ENABLE_BOCHS
22 KDP_DEBUG_MODE KdpDebugMode = {{{.Bochs=TRUE}}};
23 #else
24 KDP_DEBUG_MODE KdpDebugMode;
25 #endif
26 PKDP_INIT_ROUTINE WrapperInitRoutine;
27 KD_DISPATCH_TABLE WrapperTable;
28 BOOLEAN KdpEarlyBreak = FALSE;
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 SerialPortInfo.ComPort = 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.BaseAddress = Value;
82 SerialPortInfo.ComPort = 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 KdDebuggerEnabled = TRUE;
121 KdDebuggerNotPresent = FALSE;
122 WrapperInitRoutine = KdpGdbStubInit;
123 }
124
125 /* Check for PICE Debugging */
126 else if (!_strnicmp(p2, "PICE", 4))
127 {
128 /* Enable it */
129 p2 += 4;
130 KdpDebugMode.Pice = TRUE;
131
132 /* Enable Debugging */
133 KdDebuggerEnabled = TRUE;
134 KdDebuggerNotPresent = FALSE;
135 }
136
137 return p2;
138 }
139
140 VOID
141 NTAPI
142 INIT_FUNCTION
143 KdpCallInitRoutine(ULONG BootPhase)
144 {
145 PLIST_ENTRY CurrentEntry;
146 PKD_DISPATCH_TABLE CurrentTable;
147
148 /* Call the registered handlers */
149 CurrentEntry = KdProviders.Flink;
150 while (CurrentEntry != &KdProviders)
151 {
152 /* Get the current table */
153 CurrentTable = CONTAINING_RECORD(CurrentEntry,
154 KD_DISPATCH_TABLE,
155 KdProvidersList);
156
157 /* Call it */
158 CurrentTable->KdpInitRoutine(CurrentTable, BootPhase);
159
160 /* Next Table */
161 CurrentEntry = CurrentEntry->Flink;
162 }
163
164 /* Call the Wrapper Init Routine */
165 if (WrapperInitRoutine)
166 WrapperTable.KdpInitRoutine(&WrapperTable, BootPhase);
167 }
168
169 BOOLEAN
170 NTAPI
171 KdInitSystem(ULONG BootPhase,
172 PLOADER_PARAMETER_BLOCK LoaderBlock)
173 {
174 ULONG Value;
175 ULONG i;
176 PCHAR CommandLine, Port, BaudRate, Irq;
177
178 /* Set Default Port Options */
179 if (BootPhase == 0)
180 {
181 /* Get the Command Line */
182 CommandLine = LoaderBlock->LoadOptions;
183
184 /* Upcase it */
185 _strupr(CommandLine);
186
187 /* XXX Check for settings that we support */
188 if (strstr(CommandLine, "BREAK")) KdpEarlyBreak = TRUE;
189 if (strstr(CommandLine, "NODEBUG")) KdDebuggerEnabled = FALSE;
190 else if (strstr(CommandLine, "CRASHDEBUG")) KdDebuggerEnabled = FALSE;
191 else if (strstr(CommandLine, "DEBUG"))
192 {
193 /* Enable the kernel debugger */
194 KdDebuggerEnabled = TRUE;
195 KdDebuggerNotPresent = FALSE;
196 #ifdef KDBG
197 /* Get the KDBG Settings */
198 KdbpGetCommandLineSettings(LoaderBlock->LoadOptions);
199 #endif
200 }
201
202 /* Get the port and baud rate */
203 Port = strstr(CommandLine, "DEBUGPORT");
204 BaudRate = strstr(CommandLine, "BAUDRATE");
205 Irq = strstr(CommandLine, "IRQ");
206
207 /* Check if we got the /DEBUGPORT parameter(s) */
208 while (Port)
209 {
210 /* Move past the actual string, to reach the port*/
211 Port += sizeof("DEBUGPORT") - 1;
212
213 /* Now get past any spaces and skip the equal sign */
214 while (*Port == ' ') Port++;
215 Port++;
216
217 /* Get the debug mode and wrapper */
218 Port = KdpGetDebugMode(Port);
219 Port = strstr(Port, "DEBUGPORT");
220 }
221
222 /* Use serial port then */
223 if (KdDebuggerEnabled && KdpDebugMode.Value == 0)
224 KdpDebugMode.Serial = TRUE;
225
226 /* Check if we got a baud rate */
227 if (BaudRate)
228 {
229 /* Move past the actual string, to reach the rate */
230 BaudRate += sizeof("BAUDRATE") - 1;
231
232 /* Now get past any spaces */
233 while (*BaudRate == ' ') BaudRate++;
234
235 /* And make sure we have a rate */
236 if (*BaudRate)
237 {
238 /* Read and set it */
239 Value = atol(BaudRate + 1);
240 if (Value) PortInfo.BaudRate = SerialPortInfo.BaudRate = Value;
241 }
242 }
243
244 /* Check Serial Port Settings [IRQ] */
245 if (Irq)
246 {
247 /* Move past the actual string, to reach the rate */
248 Irq += sizeof("IRQ") - 1;
249
250 /* Now get past any spaces */
251 while (*Irq == ' ') Irq++;
252
253 /* And make sure we have an IRQ */
254 if (*Irq)
255 {
256 /* Read and set it */
257 Value = atol(Irq + 1);
258 if (Value) KdpPortIrq = Value;
259 }
260 }
261
262 /* Call Providers at Phase 0 */
263 for (i = 0; i < KdMax; i++)
264 {
265 InitRoutines[i](&DispatchTable[i], 0);
266 }
267
268 /* Call Wrapper at Phase 0 */
269 if (WrapperInitRoutine) WrapperInitRoutine(&WrapperTable, 0);
270 return TRUE;
271 }
272 else /* BootPhase > 0 */
273 {
274 #ifdef _M_IX86
275 KdpEnableSafeMem();
276 #endif
277 }
278
279 /* Call the Initialization Routines of the Registered Providers */
280 KdpCallInitRoutine(BootPhase);
281
282 /* Return success */
283 return TRUE;
284 }
285
286 /* EOF */