e74d1da2ae7549a6eb62a6841967ad2126417e4e
[reactos.git] / reactos / boot / freeldr / freeldr / debug.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <freeldr.h>
21
22 #include <debug.h>
23
24 #if DBG && !defined(_M_ARM)
25
26 //#define DEBUG_ALL
27 //#define DEBUG_INIFILE
28 //#define DEBUG_REACTOS
29 //#define DEBUG_CUSTOM
30 #define DEBUG_NONE
31
32 #define DBG_DEFAULT_LEVELS (ERR_LEVEL|FIXME_LEVEL)
33
34 #define SCREEN 1
35 #define RS232 2
36 #define BOCHS 4
37
38 #define COM1 1
39 #define COM2 2
40 #define COM3 3
41 #define COM4 4
42
43 #define BOCHS_OUTPUT_PORT 0xe9
44
45
46 static UCHAR DbgChannels[DBG_CHANNELS_COUNT];
47
48 ULONG DebugPort = RS232;
49 //ULONG DebugPort = SCREEN;
50 //ULONG DebugPort = BOCHS;
51 //ULONG DebugPort = SCREEN|BOCHS;
52 ULONG ComPort = COM1;
53 //ULONG BaudRate = 19200;
54 ULONG BaudRate = 115200;
55
56 BOOLEAN DebugStartOfLine = TRUE;
57
58 VOID DebugInit(VOID)
59 {
60 #if defined (DEBUG_ALL)
61 memset(DbgChannels, MAX_LEVEL, DBG_CHANNELS_COUNT);
62 #else
63 memset(DbgChannels, 0, DBG_CHANNELS_COUNT);
64 #endif
65
66 #if defined (DEBUG_INIFILE)
67 DbgChannels[DPRINT_INIFILE] = MAX_LEVEL;
68 #elif defined (DEBUG_REACTOS)
69 DbgChannels[DPRINT_REACTOS] = MAX_LEVEL;
70 DbgChannels[DPRINT_REGISTRY] = MAX_LEVEL;
71 #elif defined (DEBUG_CUSTOM)
72 DbgChannels[DPRINT_WARNING] = MAX_LEVEL;
73 DbgChannels[DPRINT_WINDOWS] = MAX_LEVEL;
74 #endif
75
76 if (DebugPort & RS232)
77 {
78 Rs232PortInitialize(ComPort, BaudRate);
79 }
80 }
81
82 VOID DebugPrintChar(UCHAR Character)
83 {
84 if (Character == '\n')
85 {
86 DebugStartOfLine = TRUE;
87 }
88
89 if (DebugPort & RS232)
90 {
91 if (Character == '\n')
92 {
93 Rs232PortPutByte('\r');
94 }
95 Rs232PortPutByte(Character);
96 }
97 if (DebugPort & BOCHS)
98 {
99 WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
100 }
101 if (DebugPort & SCREEN)
102 {
103 MachConsPutChar(Character);
104 }
105 }
106
107 ULONG
108 DbgPrint(const char *Format, ...)
109 {
110 int i;
111 int Length;
112 va_list ap;
113 CHAR Buffer[512];
114
115 va_start(ap, Format);
116 Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
117 va_end(ap);
118
119 /* Check if we went past the buffer */
120 if (Length == -1)
121 {
122 /* Terminate it if we went over-board */
123 Buffer[sizeof(Buffer) - 1] = '\n';
124
125 /* Put maximum */
126 Length = sizeof(Buffer);
127 }
128
129 for (i = 0; i < Length; i++)
130 {
131 DebugPrintChar(Buffer[i]);
132 }
133
134 return 0;
135 }
136
137 VOID
138 DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, ...)
139 {
140 va_list ap;
141 char Buffer[2096];
142 char *ptr = Buffer;
143
144 // Mask out unwanted debug messages
145 if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS ))
146 {
147 return;
148 }
149
150 // Print the header if we have started a new line
151 if (DebugStartOfLine)
152 {
153 DbgPrint("(%s:%lu) ", File, Line);
154
155 switch (Level)
156 {
157 case ERR_LEVEL:
158 DbgPrint("err: ");
159 break;
160 case FIXME_LEVEL:
161 DbgPrint("fixme: ");
162 break;
163 case WARN_LEVEL:
164 DbgPrint("warn: ");
165 break;
166 case TRACE_LEVEL:
167 DbgPrint("trace: ");
168 break;
169 }
170
171 DebugStartOfLine = FALSE;
172 }
173
174 va_start(ap, Format);
175 vsprintf(Buffer, Format, ap);
176 va_end(ap);
177
178 while (*ptr)
179 {
180 DebugPrintChar(*ptr++);
181 }
182 }
183
184 VOID
185 DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length)
186 {
187 PUCHAR BufPtr = (PUCHAR)Buffer;
188 ULONG Idx;
189 ULONG Idx2;
190
191 // Mask out unwanted debug messages
192 if (!(DbgChannels[Mask] & TRACE_LEVEL))
193 {
194 return;
195 }
196
197 DebugStartOfLine = FALSE; // We don't want line headers
198 DbgPrint("Dumping buffer at %p with length of %lu bytes:\n", Buffer, Length);
199
200 for (Idx=0; Idx<Length; )
201 {
202 DebugStartOfLine = FALSE; // We don't want line headers
203
204 if (Idx < 0x0010)
205 {
206 DbgPrint("000%x:\t", Idx);
207 }
208 else if (Idx < 0x0100)
209 {
210 DbgPrint("00%x:\t", Idx);
211 }
212 else if (Idx < 0x1000)
213 {
214 DbgPrint("0%x:\t", Idx);
215 }
216 else
217 {
218 DbgPrint("%x:\t", Idx);
219 }
220
221 for (Idx2=0; Idx2<16; Idx2++,Idx++)
222 {
223 if (BufPtr[Idx] < 0x10)
224 {
225 DbgPrint("0");
226 }
227 DbgPrint("%x", BufPtr[Idx]);
228
229 if (Idx2 == 7)
230 {
231 DbgPrint("-");
232 }
233 else
234 {
235 DbgPrint(" ");
236 }
237 }
238
239 Idx -= 16;
240 DbgPrint(" ");
241
242 for (Idx2=0; Idx2<16; Idx2++,Idx++)
243 {
244 if ((BufPtr[Idx] > 20) && (BufPtr[Idx] < 0x80))
245 {
246 DbgPrint("%c", BufPtr[Idx]);
247 }
248 else
249 {
250 DbgPrint(".");
251 }
252 }
253
254 DbgPrint("\n");
255 }
256 }
257
258 static BOOLEAN
259 DbgAddDebugChannel( CHAR* channel, CHAR* level, CHAR op)
260 {
261 int iLevel, iChannel;
262
263 if(channel == NULL || *channel == L'\0' ||strlen(channel) == 0 )
264 return FALSE;
265
266 if(level == NULL || *level == L'\0' ||strlen(level) == 0 )
267 iLevel = MAX_LEVEL;
268 else if(strcmp(level, "err") == 0)
269 iLevel = ERR_LEVEL;
270 else if(strcmp(level, "fixme") == 0)
271 iLevel = FIXME_LEVEL;
272 else if(strcmp(level, "warn") == 0)
273 iLevel = WARN_LEVEL;
274 else if (strcmp(level, "trace") == 0)
275 iLevel = TRACE_LEVEL;
276 else
277 return FALSE;
278
279 if(strcmp(channel, "memory") == 0) iChannel = DPRINT_MEMORY;
280 else if(strcmp(channel, "filesystem") == 0) iChannel = DPRINT_FILESYSTEM;
281 else if(strcmp(channel, "inifile") == 0) iChannel = DPRINT_INIFILE;
282 else if(strcmp(channel, "ui") == 0) iChannel = DPRINT_UI;
283 else if(strcmp(channel, "disk") == 0) iChannel = DPRINT_DISK;
284 else if(strcmp(channel, "cache") == 0) iChannel = DPRINT_CACHE;
285 else if(strcmp(channel, "registry") == 0) iChannel = DPRINT_REGISTRY;
286 else if(strcmp(channel, "linux") == 0) iChannel = DPRINT_LINUX;
287 else if(strcmp(channel, "hwdetect") == 0) iChannel = DPRINT_HWDETECT;
288 else if(strcmp(channel, "windows") == 0) iChannel = DPRINT_WINDOWS;
289 else if(strcmp(channel, "peloader") == 0) iChannel = DPRINT_PELOADER;
290 else if(strcmp(channel, "scsiport") == 0) iChannel = DPRINT_SCSIPORT;
291 else if(strcmp(channel, "heap") == 0) iChannel = DPRINT_HEAP;
292 else if(strcmp(channel, "all") == 0)
293 {
294 int i;
295
296 for(i= 0 ; i < DBG_CHANNELS_COUNT; i++)
297 {
298 if(op==L'+')
299 DbgChannels[i] |= iLevel;
300 else
301 DbgChannels[i] &= ~iLevel;
302 }
303
304 return TRUE;
305 }
306
307 if(op==L'+')
308 DbgChannels[iChannel] |= iLevel;
309 else
310 DbgChannels[iChannel] &= ~iLevel;
311
312 return TRUE;
313 }
314
315 VOID
316 DbgParseDebugChannels(PCHAR Value)
317 {
318 CHAR *str, *separator, *c, op;
319
320 str = Value;
321
322 do
323 {
324 separator = strchr(str, L',');
325 if(separator != NULL)
326 *separator = L'\0';
327
328 c = strchr(str, L'+');
329 if(c == NULL)
330 c = strchr(str, L'-');
331
332 if(c != NULL)
333 {
334 op = *c;
335 *c = L'\0';
336 c++;
337
338 DbgAddDebugChannel(c, str, op);
339 }
340
341 str = separator + 1;
342 } while(separator != NULL);
343 }
344
345 #else
346
347 ULONG
348 DbgPrint(PCCH Format, ...)
349 {
350 return 0;
351 }
352
353 #endif // DBG
354
355 ULONG
356 MsgBoxPrint(const char *Format, ...)
357 {
358 va_list ap;
359 CHAR Buffer[512];
360 ULONG Length;
361
362 va_start(ap, Format);
363
364 /* Construct a string */
365 Length = _vsnprintf(Buffer, 512, Format, ap);
366
367 /* Check if we went past the buffer */
368 if (Length == MAXULONG)
369 {
370 /* Terminate it if we went over-board */
371 Buffer[sizeof(Buffer) - 1] = '\n';
372
373 /* Put maximum */
374 Length = sizeof(Buffer);
375 }
376
377 /* Show it as a message box */
378 UiMessageBox(Buffer);
379
380 /* Cleanup and exit */
381 va_end(ap);
382 return 0;
383 }
384
385 //DECLSPEC_NORETURN
386 VOID
387 NTAPI
388 KeBugCheckEx(
389 IN ULONG BugCheckCode,
390 IN ULONG_PTR BugCheckParameter1,
391 IN ULONG_PTR BugCheckParameter2,
392 IN ULONG_PTR BugCheckParameter3,
393 IN ULONG_PTR BugCheckParameter4)
394 {
395 char Buffer[70];
396 sprintf(Buffer, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)",
397 BugCheckCode, BugCheckParameter1, BugCheckParameter2,
398 BugCheckParameter3, BugCheckParameter4);
399 UiMessageBoxCritical(Buffer);
400 assert(FALSE);
401 for (;;);
402 }
403
404 VOID
405 NTAPI
406 RtlAssert(IN PVOID FailedAssertion,
407 IN PVOID FileName,
408 IN ULONG LineNumber,
409 IN PCHAR Message OPTIONAL)
410 {
411 if (Message)
412 {
413 DbgPrint("Assertion \'%s\' failed at %s line %d: %s\n",
414 (PCHAR)FailedAssertion,
415 (PCHAR)FileName,
416 LineNumber,
417 Message);
418 }
419 else
420 {
421 DbgPrint("Assertion \'%s\' failed at %s line %d\n",
422 (PCHAR)FailedAssertion,
423 (PCHAR)FileName,
424 LineNumber);
425 }
426
427 DbgBreakPoint();
428 }