ReactOS 0.4.15-dev-8061-g57b775e
debug.c
Go to the documentation of this file.
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#include <debug.h>
22
23#if DBG
24
25// #define DEBUG_ALL
26// #define DEBUG_WARN
27// #define DEBUG_ERR
28// #define DEBUG_INIFILE
29// #define DEBUG_REACTOS
30// #define DEBUG_CUSTOM
31#define DEBUG_NONE
32
33#define DBG_DEFAULT_LEVELS (ERR_LEVEL|FIXME_LEVEL)
34
35static UCHAR DbgChannels[DBG_CHANNELS_COUNT];
36
37#define SCREEN 1
38#define RS232 2
39#define BOCHS 4
40
41#define BOCHS_OUTPUT_PORT 0xE9
42
43ULONG DebugPort = RS232;
44
45/* Serial debug connection */
46#if defined(SARCH_PC98)
47ULONG BaudRate = 9600;
48#else
49ULONG BaudRate = 115200;
50#endif
51
52ULONG ComPort = 0; // The COM port initializer chooses the first available port starting from COM4 down to COM1.
53ULONG PortIrq = 0; // Not used at the moment.
54
55BOOLEAN DebugStartOfLine = TRUE;
56
57#ifdef UEFIBOOT
58VOID
59ARMWriteToUART(UCHAR Data);
60#endif
61
62VOID
65{
66 static BOOLEAN Initialized = FALSE;
67 PSTR CommandLine, PortString, BaudString, IrqString;
69 CHAR DbgStringBuffer[256];
70
71 /* Always reset the debugging channels */
72
73#if defined (DEBUG_ALL)
74 memset(DbgChannels, MAX_LEVEL, DBG_CHANNELS_COUNT);
75#elif defined (DEBUG_WARN)
76 memset(DbgChannels, WARN_LEVEL|FIXME_LEVEL|ERR_LEVEL, DBG_CHANNELS_COUNT);
77#elif defined (DEBUG_ERR)
78 memset(DbgChannels, ERR_LEVEL, DBG_CHANNELS_COUNT);
79#else
80 memset(DbgChannels, 0, DBG_CHANNELS_COUNT);
81#endif
82
83#if defined (DEBUG_INIFILE)
84 DbgChannels[DPRINT_INIFILE] = MAX_LEVEL;
85#elif defined (DEBUG_REACTOS)
86 DbgChannels[DPRINT_REACTOS] = MAX_LEVEL;
87 DbgChannels[DPRINT_REGISTRY] = MAX_LEVEL;
88#elif defined (DEBUG_CUSTOM)
89 DbgChannels[DPRINT_WARNING] = MAX_LEVEL;
90 DbgChannels[DPRINT_WINDOWS] = MAX_LEVEL;
91#endif
92
93 CommandLine = NULL;
94 if (!DebugString || !*DebugString)
95 {
96 /* No command-line is provided: during pre-initialization,
97 * initialize the debug port with default settings;
98 * otherwise just return during main initialization */
99 if (!Initialized)
100 goto Done;
101 return;
102 }
103
104 /* Get a copy of the command-line */
105 strcpy(DbgStringBuffer, DebugString);
106 CommandLine = DbgStringBuffer;
107
108 /* Upcase it */
109 _strupr(CommandLine);
110
111 /* Get the port and baud rate */
112 PortString = strstr(CommandLine, "DEBUGPORT");
113 BaudString = strstr(CommandLine, "BAUDRATE");
114 IrqString = strstr(CommandLine, "IRQ");
115
116 /*
117 * Check if we got /DEBUGPORT parameters.
118 * NOTE: Inspired by reactos/ntoskrnl/kd/kdinit.c, KdInitSystem(...)
119 */
120 while (PortString)
121 {
122 /* Move past the actual string, to reach the port*/
123 PortString += strlen("DEBUGPORT");
124
125 /* Now get past any spaces and skip the equal sign */
126 while (*PortString == ' ') PortString++;
127 PortString++;
128
129 /* Check for possible ports and set the port to use */
130 if (strncmp(PortString, "SCREEN", 6) == 0)
131 {
132 PortString += 6;
133 DebugPort |= SCREEN;
134 }
135 else if (strncmp(PortString, "BOCHS", 5) == 0)
136 {
137 PortString += 5;
138 DebugPort |= BOCHS;
139 }
140 else if (strncmp(PortString, "COM", 3) == 0)
141 {
142 PortString += 3;
143 DebugPort |= RS232;
144
145 /* Set the port to use */
146 Value = atol(PortString);
147 if (Value) ComPort = Value;
148 }
149
150 PortString = strstr(PortString, "DEBUGPORT");
151 }
152
153 /* Check if we got a baud rate */
154 if (BaudString)
155 {
156 /* Move past the actual string, to reach the rate */
157 BaudString += strlen("BAUDRATE");
158
159 /* Now get past any spaces */
160 while (*BaudString == ' ') BaudString++;
161
162 /* And make sure we have a rate */
163 if (*BaudString)
164 {
165 /* Read and set it */
166 Value = atol(BaudString + 1);
167 if (Value) BaudRate = Value;
168 }
169 }
170
171 /* Check Serial Port Settings [IRQ] */
172 if (IrqString)
173 {
174 /* Move past the actual string, to reach the rate */
175 IrqString += strlen("IRQ");
176
177 /* Now get past any spaces */
178 while (*IrqString == ' ') IrqString++;
179
180 /* And make sure we have an IRQ */
181 if (*IrqString)
182 {
183 /* Read and set it */
184 Value = atol(IrqString + 1);
185 if (Value) PortIrq = Value;
186 }
187 }
188
189Done:
191
192 /* Try to initialize the port; if it fails, remove the corresponding flag */
193 if (DebugPort & RS232)
194 {
195 if (!Rs232PortInitialize(ComPort, BaudRate))
196 DebugPort &= ~RS232;
197 }
198}
199
200VOID DebugPrintChar(UCHAR Character)
201{
202 if (Character == '\n')
203 DebugStartOfLine = TRUE;
204
205 if (DebugPort & RS232)
206 {
207 if (Character == '\n')
208 Rs232PortPutByte('\r');
209
210 Rs232PortPutByte(Character);
211 }
212 if (DebugPort & BOCHS)
213 {
214 WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
215 }
216 if (DebugPort & SCREEN)
217 {
218 MachConsPutChar(Character);
219 }
220}
221
222ULONG
223DbgPrint(const char *Format, ...)
224{
225 va_list ap;
226 int Length;
227 char* ptr;
228 CHAR Buffer[512];
229
231 Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
232 va_end(ap);
233
234 /* Check if we went past the buffer */
235 if (Length == -1)
236 {
237 /* Terminate it if we went over-board */
238 Buffer[sizeof(Buffer) - 1] = '\n';
239
240 /* Put maximum */
241 Length = sizeof(Buffer);
242 }
243
244 ptr = Buffer;
245 while (Length--)
246 DebugPrintChar(*ptr++);
247
248 return 0;
249}
250
251VOID
252DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, ...)
253{
254 va_list ap;
255 char Buffer[2096];
256 char *ptr = Buffer;
257
258 /* Mask out unwanted debug messages */
259 if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS))
260 {
261 return;
262 }
263
264 /* Print the header if we have started a new line */
265 if (DebugStartOfLine)
266 {
267 DbgPrint("(%s:%lu) ", File, Line);
268
269 switch (Level)
270 {
271 case ERR_LEVEL:
272 DbgPrint("err: ");
273 break;
274 case FIXME_LEVEL:
275 DbgPrint("fixme: ");
276 break;
277 case WARN_LEVEL:
278 DbgPrint("warn: ");
279 break;
280 case TRACE_LEVEL:
281 DbgPrint("trace: ");
282 break;
283 }
284
285 DebugStartOfLine = FALSE;
286 }
287
290 va_end(ap);
291
292 while (*ptr)
293 {
294 DebugPrintChar(*ptr++);
295 }
296}
297
298VOID
299DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length)
300{
301 PUCHAR BufPtr = (PUCHAR)Buffer;
303
304 /* Mask out unwanted debug messages */
305 if (!(DbgChannels[Mask] & TRACE_LEVEL))
306 return;
307
308 DebugStartOfLine = FALSE; // We don't want line headers
309 DbgPrint("Dumping buffer at %p with length of %lu bytes:\n", Buffer, Length);
310
311 Offset = 0;
312 while (Offset < Length)
313 {
314 /* We don't want line headers */
315 DebugStartOfLine = FALSE;
316
317 /* Print the offset */
318 DbgPrint("%04x:\t", Offset);
319
320 /* Print either 16 or the remaining number of bytes */
321 Count = min(Length - Offset, 16);
322 for (i = 0; i < Count; i++, Offset++)
323 {
324 DbgPrint("%02x%c", BufPtr[Offset], (i == 7) ? '-' : ' ');
325 }
326
327 DbgPrint("\n");
328 }
329}
330
331VOID
333{
334 DebugPort &= ~SCREEN;
335}
336
337static BOOLEAN
338DbgAddDebugChannel(CHAR* channel, CHAR* level, CHAR op)
339{
340 int iLevel, iChannel;
341
342 if (channel == NULL || *channel == '\0' || strlen(channel) == 0)
343 return FALSE;
344
345 if (level == NULL || *level == '\0' || strlen(level) == 0)
346 iLevel = MAX_LEVEL;
347 else if (strcmp(level, "err") == 0)
348 iLevel = ERR_LEVEL;
349 else if (strcmp(level, "fixme") == 0)
350 iLevel = FIXME_LEVEL;
351 else if (strcmp(level, "warn") == 0)
352 iLevel = WARN_LEVEL;
353 else if (strcmp(level, "trace") == 0)
354 iLevel = TRACE_LEVEL;
355 else
356 return FALSE;
357
358 if (strcmp(channel, "memory" ) == 0) iChannel = DPRINT_MEMORY;
359 else if (strcmp(channel, "filesystem") == 0) iChannel = DPRINT_FILESYSTEM;
360 else if (strcmp(channel, "inifile" ) == 0) iChannel = DPRINT_INIFILE;
361 else if (strcmp(channel, "ui" ) == 0) iChannel = DPRINT_UI;
362 else if (strcmp(channel, "disk" ) == 0) iChannel = DPRINT_DISK;
363 else if (strcmp(channel, "cache" ) == 0) iChannel = DPRINT_CACHE;
364 else if (strcmp(channel, "registry" ) == 0) iChannel = DPRINT_REGISTRY;
365 else if (strcmp(channel, "linux" ) == 0) iChannel = DPRINT_LINUX;
366 else if (strcmp(channel, "hwdetect" ) == 0) iChannel = DPRINT_HWDETECT;
367 else if (strcmp(channel, "windows" ) == 0) iChannel = DPRINT_WINDOWS;
368 else if (strcmp(channel, "peloader" ) == 0) iChannel = DPRINT_PELOADER;
369 else if (strcmp(channel, "scsiport" ) == 0) iChannel = DPRINT_SCSIPORT;
370 else if (strcmp(channel, "heap" ) == 0) iChannel = DPRINT_HEAP;
371 else if (strcmp(channel, "all" ) == 0)
372 {
373 int i;
374
375 for (i = 0; i < DBG_CHANNELS_COUNT; i++)
376 {
377 if (op == '+')
378 DbgChannels[i] |= iLevel;
379 else
380 DbgChannels[i] &= ~iLevel;
381 }
382
383 return TRUE;
384 }
385 else return FALSE;
386
387 if (op == '+')
388 DbgChannels[iChannel] |= iLevel;
389 else
390 DbgChannels[iChannel] &= ~iLevel;
391
392 return TRUE;
393}
394
395VOID
397{
398 CHAR *str, *separator, *c, op;
399
400 str = Value;
401
402 do
403 {
404 separator = strchr(str, ',');
405 if (separator != NULL)
406 *separator = '\0';
407
408 c = strchr(str, '+');
409 if (c == NULL)
410 c = strchr(str, '-');
411
412 if (c != NULL)
413 {
414 op = *c;
415 *c = '\0';
416 c++;
417
418 DbgAddDebugChannel(c, str, op);
419 }
420
421 str = separator + 1;
422 } while (separator != NULL);
423}
424
425#else
426
427ULONG
429{
430 return 0;
431}
432
433#endif // DBG
434
435ULONG
436MsgBoxPrint(const char *Format, ...)
437{
438 va_list ap;
439 CHAR Buffer[512];
441
443
444 /* Construct a string */
445 Length = _vsnprintf(Buffer, 512, Format, ap);
446
447 /* Check if we went past the buffer */
448 if (Length == MAXULONG)
449 {
450 /* Terminate it if we went over-board */
451 Buffer[sizeof(Buffer) - 1] = '\n';
452
453 /* Put maximum */
454 Length = sizeof(Buffer);
455 }
456
457 /* Show it as a message box */
459
460 /* Cleanup and exit */
461 va_end(ap);
462 return 0;
463}
464
466VOID
467NTAPI
469 IN ULONG BugCheckCode,
470 IN ULONG_PTR BugCheckParameter1,
471 IN ULONG_PTR BugCheckParameter2,
472 IN ULONG_PTR BugCheckParameter3,
473 IN ULONG_PTR BugCheckParameter4)
474{
475 char Buffer[70];
476
478 "*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)",
479 BugCheckCode,
480 (PVOID)BugCheckParameter1,
481 (PVOID)BugCheckParameter2,
482 (PVOID)BugCheckParameter3,
483 (PVOID)BugCheckParameter4);
484
486 ASSERT(FALSE);
487 for (;;);
488}
489
490VOID
491NTAPI
492RtlAssert(IN PVOID FailedAssertion,
496{
497 if (Message)
498 {
499 DbgPrint("Assertion \'%s\' failed at %s line %lu: %s\n",
500 (PCHAR)FailedAssertion,
503 Message);
504 }
505 else
506 {
507 DbgPrint("Assertion \'%s\' failed at %s line %lu\n",
508 (PCHAR)FailedAssertion,
510 LineNumber);
511 }
512
514}
515
517{
518 "TEST_BUGCHECK",
519 "MISSING_HARDWARE_REQUIREMENTS",
520 "FREELDR_IMAGE_CORRUPTION",
521 "MEMORY_INIT_FAILURE",
522#ifdef UEFIBOOT
523 "EXIT_BOOTSERVICES_FAILURE",
524#endif
525};
526
unsigned char BOOLEAN
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 LineNumber
Definition: acpixf.h:1220
BOOLEAN Rs232PortInitialize(IN ULONG ComPort, IN ULONG BaudRate)
Definition: debug.c:15
VOID Rs232PortPutByte(UCHAR ByteToSend)
Definition: debug.c:22
#define DPRINT_CACHE
Definition: debug.h:30
#define DPRINT_LINUX
Definition: debug.h:33
#define DPRINT_UI
Definition: debug.h:28
#define DbgParseDebugChannels(val)
Definition: debug.h:124
#define DPRINT_FILESYSTEM
Definition: debug.h:26
#define DebugInit(DebugString)
Definition: debug.h:120
#define DPRINT_SCSIPORT
Definition: debug.h:37
#define DBG_CHANNELS_COUNT
Definition: debug.h:39
#define DPRINT_HEAP
Definition: debug.h:38
#define DPRINT_INIFILE
Definition: debug.h:27
#define DPRINT_REACTOS
Definition: debug.h:32
#define DPRINT_HWDETECT
Definition: debug.h:34
#define DPRINT_REGISTRY
Definition: debug.h:31
#define DPRINT_DISK
Definition: debug.h:29
#define DPRINT_WINDOWS
Definition: debug.h:35
#define DebugDisableScreenPort()
Definition: debug.h:123
#define DPRINT_MEMORY
Definition: debug.h:25
#define DPRINT_WARNING
Definition: debug.h:24
#define DPRINT_PELOADER
Definition: debug.h:36
#define MachConsPutChar(Ch)
Definition: machine.h:86
VOID UiMessageBoxCritical(_In_ PCSTR MessageText)
Definition: ui.c:372
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
ULONG_PTR BugCheckInfo[5]
Definition: debug.c:527
char * BugCodeStrings[]
Definition: debug.c:516
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:468
ULONG MsgBoxPrint(const char *Format,...)
Definition: debug.c:436
VOID NTAPI RtlAssert(IN PVOID FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCHAR Message OPTIONAL)
Definition: debug.c:492
static CCHAR DebugString[256]
Definition: settings.c:16
Definition: bufpool.h:45
Definition: File.h:16
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
static const WCHAR separator[]
Definition: asmname.c:65
static const WCHAR Message[]
Definition: register.c:74
unsigned int Mask
Definition: fpcontrol.c:82
GLint level
Definition: gl.h:1546
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define c
Definition: ke_i.h:80
#define ASSERT(a)
Definition: mode.c:44
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define min(a, b)
Definition: monoChain.cc:55
#define _In_
Definition: ms_sal.h:308
@ Initialized
Definition: ketypes.h:388
int Count
Definition: noreturn.cpp:7
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
CONST CHAR * PCCH
Definition: ntbasedef.h:392
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
const WCHAR * str
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
#define memset(x, y, z)
Definition: compat.h:39
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: ncftp.h:79
#define MAXULONG
Definition: typedefs.h:251
char * PSTR
Definition: typedefs.h:51
#define NTAPI
Definition: typedefs.h:36
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
#define _vsnprintf
Definition: xmlstorage.h:202
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175