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