sync with trunk r46493
[reactos.git] / 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 #if defined (DEBUG_ALL)
33 ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
34 DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
35 DPRINT_LINUX | DPRINT_HWDETECT;
36 #elif defined (DEBUG_INIFILE)
37 ULONG DebugPrintMask = DPRINT_INIFILE;
38 #elif defined (DEBUG_REACTOS)
39 ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
40 #elif defined (DEBUG_CUSTOM)
41 ULONG DebugPrintMask = DPRINT_WARNING |
42 DPRINT_UI | DPRINT_CACHE | DPRINT_REACTOS |
43 DPRINT_LINUX;
44 #else //#elif defined (DEBUG_NONE)
45 ULONG DebugPrintMask = 0;
46 #endif
47
48 #define SCREEN 1
49 #define RS232 2
50 #define BOCHS 4
51
52 #define COM1 1
53 #define COM2 2
54 #define COM3 3
55 #define COM4 4
56
57 #define BOCHS_OUTPUT_PORT 0xe9
58
59 ULONG DebugPort = RS232;
60 //ULONG DebugPort = SCREEN;
61 //ULONG DebugPort = BOCHS;
62 //ULONG DebugPort = SCREEN|BOCHS;
63 ULONG ComPort = COM1;
64 //ULONG BaudRate = 19200;
65 ULONG BaudRate = 115200;
66
67 BOOLEAN DebugStartOfLine = TRUE;
68
69 VOID DebugInit(VOID)
70 {
71 if (DebugPort & RS232)
72 {
73 Rs232PortInitialize(ComPort, BaudRate);
74 }
75 }
76
77 VOID DebugPrintChar(UCHAR Character)
78 {
79 if (Character == '\n')
80 {
81 DebugStartOfLine = TRUE;
82 }
83
84 if (DebugPort & RS232)
85 {
86 if (Character == '\n')
87 {
88 Rs232PortPutByte('\r');
89 }
90 Rs232PortPutByte(Character);
91 }
92 if (DebugPort & BOCHS)
93 {
94 WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
95 }
96 if (DebugPort & SCREEN)
97 {
98 MachConsPutChar(Character);
99 }
100 }
101
102 ULONG
103 DbgPrint(const char *Format, ...)
104 {
105 int i;
106 int Length;
107 va_list ap;
108 CHAR Buffer[512];
109
110 va_start(ap, Format);
111 Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
112 va_end(ap);
113
114 /* Check if we went past the buffer */
115 if (Length == -1)
116 {
117 /* Terminate it if we went over-board */
118 Buffer[sizeof(Buffer) - 1] = '\n';
119
120 /* Put maximum */
121 Length = sizeof(Buffer);
122 }
123
124 for (i = 0; i < Length; i++)
125 {
126 DebugPrintChar(Buffer[i]);
127 }
128
129 return 0;
130 }
131
132 VOID DebugPrintHeader(ULONG Mask)
133 {
134 /* No header */
135 if (Mask == 0)
136 return;
137
138 switch (Mask)
139 {
140 case DPRINT_WARNING:
141 DbgPrint("WARNING: ");
142 break;
143 case DPRINT_MEMORY:
144 DbgPrint("MEMORY: ");
145 break;
146 case DPRINT_FILESYSTEM:
147 DbgPrint("FILESYS: ");
148 break;
149 case DPRINT_INIFILE:
150 DbgPrint("INIFILE: ");
151 break;
152 case DPRINT_UI:
153 DbgPrint("UI: ");
154 break;
155 case DPRINT_DISK:
156 DbgPrint("DISK: ");
157 break;
158 case DPRINT_CACHE:
159 DbgPrint("CACHE: ");
160 break;
161 case DPRINT_REGISTRY:
162 DbgPrint("REGISTRY: ");
163 break;
164 case DPRINT_REACTOS:
165 DbgPrint("REACTOS: ");
166 break;
167 case DPRINT_LINUX:
168 DbgPrint("LINUX: ");
169 break;
170 case DPRINT_WINDOWS:
171 DbgPrint("WINLDR: ");
172 break;
173 case DPRINT_HWDETECT:
174 DbgPrint("HWDETECT: ");
175 break;
176 case DPRINT_PELOADER:
177 DbgPrint("PELOADER: ");
178 break;
179 case DPRINT_SCSIPORT:
180 DbgPrint("SCSIPORT: ");
181 break;
182 default:
183 DbgPrint("UNKNOWN: ");
184 break;
185 }
186 }
187
188 char* g_file;
189 int g_line;
190
191 VOID DbgPrintMask(ULONG Mask, char *format, ...)
192 {
193 va_list ap;
194 char Buffer[2096];
195 char *ptr = Buffer;
196
197 // Mask out unwanted debug messages
198 if (!(Mask & DebugPrintMask))
199 {
200 return;
201 }
202
203 // Disable file/line for scsiport messages
204 if (Mask & DPRINT_SCSIPORT)
205 {
206 DebugStartOfLine = FALSE;
207 }
208
209 // Print the header if we have started a new line
210 if (DebugStartOfLine)
211 {
212 DbgPrint("(%s:%d) ", g_file, g_line);
213 DebugPrintHeader(Mask);
214 DebugStartOfLine = FALSE;
215 }
216
217 va_start(ap, format);
218 vsprintf(Buffer, format, ap);
219 va_end(ap);
220
221 while (*ptr)
222 {
223 DebugPrintChar(*ptr++);
224 }
225 }
226
227 VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length)
228 {
229 PUCHAR BufPtr = (PUCHAR)Buffer;
230 ULONG Idx;
231 ULONG Idx2;
232
233 // Mask out unwanted debug messages
234 if (!(Mask & DebugPrintMask))
235 {
236 return;
237 }
238
239 DebugStartOfLine = FALSE; // We don't want line headers
240 DbgPrintMask(Mask, "Dumping buffer at 0x%x with length of %d bytes:\n", Buffer, Length);
241
242 for (Idx=0; Idx<Length; )
243 {
244 DebugStartOfLine = FALSE; // We don't want line headers
245
246 if (Idx < 0x0010)
247 {
248 DbgPrintMask(Mask, "000%x:\t", Idx);
249 }
250 else if (Idx < 0x0100)
251 {
252 DbgPrintMask(Mask, "00%x:\t", Idx);
253 }
254 else if (Idx < 0x1000)
255 {
256 DbgPrintMask(Mask, "0%x:\t", Idx);
257 }
258 else
259 {
260 DbgPrintMask(Mask, "%x:\t", Idx);
261 }
262
263 for (Idx2=0; Idx2<16; Idx2++,Idx++)
264 {
265 if (BufPtr[Idx] < 0x10)
266 {
267 DbgPrintMask(Mask, "0");
268 }
269 DbgPrintMask(Mask, "%x", BufPtr[Idx]);
270
271 if (Idx2 == 7)
272 {
273 DbgPrintMask(Mask, "-");
274 }
275 else
276 {
277 DbgPrintMask(Mask, " ");
278 }
279 }
280
281 Idx -= 16;
282 DbgPrintMask(Mask, " ");
283
284 for (Idx2=0; Idx2<16; Idx2++,Idx++)
285 {
286 if ((BufPtr[Idx] > 20) && (BufPtr[Idx] < 0x80))
287 {
288 DbgPrintMask(Mask, "%c", BufPtr[Idx]);
289 }
290 else
291 {
292 DbgPrintMask(Mask, ".");
293 }
294 }
295
296 DbgPrintMask(Mask, "\n");
297 }
298 }
299
300 #else
301
302 VOID DbgPrintMask(ULONG Mask, char *format, ...)
303 {
304 }
305
306 ULONG DbgPrint(PCCH Format, ...)
307 {
308 return 0;
309 }
310
311 #endif // DBG
312
313 ULONG
314 MsgBoxPrint(const char *Format, ...)
315 {
316 va_list ap;
317 CHAR Buffer[512];
318 ULONG Length;
319
320 va_start(ap, Format);
321
322 /* Construct a string */
323 Length = _vsnprintf(Buffer, 512, Format, ap);
324
325 /* Check if we went past the buffer */
326 if (Length == MAXULONG)
327 {
328 /* Terminate it if we went over-board */
329 Buffer[sizeof(Buffer) - 1] = '\n';
330
331 /* Put maximum */
332 Length = sizeof(Buffer);
333 }
334
335 /* Show it as a message box */
336 UiMessageBox(Buffer);
337
338 /* Cleanup and exit */
339 va_end(ap);
340 return 0;
341 }
342
343 NTKERNELAPI
344 DECLSPEC_NORETURN
345 VOID
346 NTAPI
347 KeBugCheckEx(
348 IN ULONG BugCheckCode,
349 IN ULONG_PTR BugCheckParameter1,
350 IN ULONG_PTR BugCheckParameter2,
351 IN ULONG_PTR BugCheckParameter3,
352 IN ULONG_PTR BugCheckParameter4)
353 {
354 char Buffer[70];
355 sprintf(Buffer, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)",
356 BugCheckCode, BugCheckParameter1, BugCheckParameter2,
357 BugCheckParameter3, BugCheckParameter4);
358 UiMessageBoxCritical(Buffer);
359 assert(FALSE);
360 for (;;);
361 }